Python and Macs
Python is a popular tool among Mac Admins. You can find a fairly comprehensive (and long) list of Python-based Mac Admin tools at Python Macadmin Tools, so it’s a handy thing to be able to throw together a Python script every now and then.
.plist files
A lot of settings in Mac OS X are managed in property lists (or .plist files), so it’s also a handy thing to be able to use a Python script to manipulate .plist files.
.plist files and Bash (Bourne Again Shell)
Generally, if you’re using bash (the default shell when you open the Terminal.app), you would read from and write to .plist files using a defaults command. For example, if you wanted to see whether the last user logged in (loggedIn) is still logged in or if no one is logged in (loggedOut or Restart), you would use a command like this:
.plist files and Python… and plistlib
This is where things get a bit tricky, because there is no equivalent to defaults in Python. Python has a module you can import called plistlib that presumably lets you read from and write to .plist files.
If you follow the examples in the documentation, though, you may run into some errors.
For example, if you paste in the code on how to generate a .plist (even if you import datetime, plistlib, and time), you’ll get an error of
That’s why I’m writing this guide, because it’s difficult to find straightforward documentation on how to actually use plistlib.
This is an actual basic script that will actually write a .plist based on a dictionary you define:
import os
import plistlib
def main():
pl = {
“aString” : “Doodah”,
“aList” : [“A”, “B”, 12, 32.1, [1, 2, 3]],
“aFloat” : 0.1,
“anInt” : 730
}
fileName=os.path.expanduser(‘~/Desktop/example.plist’)
plistlib.writePlist(pl, fileName)
if __name__ == ‘__main__’:
main()
import os
import plistlib
def main():
fileName=os.path.expanduser(‘~/Desktop/example.plist’)
if os.path.exists(fileName):
pl=plistlib.readPlist(fileName)
print ‘\nThe plist full contents is %s\n’ % pl
if ‘aString’ in pl:
print ‘The aString value is %s\n’ % pl[‘aString’]
else:
print ‘There is no aString in the plist\n’
else:
print ‘%s does not exist, so can\’t be read’ % fileName
if __name__ == ‘__main__’:
main()
File “./NAMEOFYOURSCRIPT.py”, line 26, in
main()
File “./NAMEOFYOURSCRIPT.py”, line 13, in main
pl=plistlib.readPlist(fileName)
File
“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plistlib.py”, line 78, in readPlist
rootObject = p.parse(pathOrFile)
File
“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plistlib.py”, line 406, in parse
parser.ParseFile(fileobj)
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 8
.plist files and Python… and FoundationPlist
Fortunately, there’s a solution for this. FoundationPlist (by Greg Neagle, author of Munki) can read from and write to both XML and binary .plist files reliably.
To use FoundationPlist, just put it and its corresponding __init__.py in a FoundationPlist subfolder of your Python script, and then put
You can see a good example of this subfolder setup in Outset’s code.
Once the FoundationPlist module is imported, you can use it similarly to how you would use plistlib:
munki_prefs=FoundationPlist.readPlist(munki_prefs_location)
manifest=munki_prefs[‘ClientIdentifier’]
print ‘The client identifier is %s’ % manifest
PlistBuddy (not Python)
If you don’t need to use Python and the defaults command isn’t cutting it for you, Macs also come with a handy built-in command-line tool called PlistBuddy that can manipulate both binary and XML .plist files. I have several tutorials on how to use PlistBuddy.
2 responses to “How to read from and write to .plist files using Python”
[…] Source: How to read from and write to .plist files using Python – St. Ignatius College Prep Tech Blog […]
you can use plutil to “convert” a binary plist to XML without writing a file. just pass ‘-o -‘ and the output will be written to stdout, which can then just be parsed directly. In fact, it may just be easier to convert it to json instead of xml.
e.g.:
plutil -convert json -o – example.plist