Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3.4 plistlib doesn't work (str vs bytes errors)

Tags:

python-3.x

So, I started on a new toy project and decided I'd use Python 3 for the first time...

In [1]: import plistlib

In [2]: with open("/Volumes/Thunderbay/CURRENT/Music/iTunes/iTunes Library.xml") as itl:
    library = plistlib.load(itl)
   ...:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-6459a022cb71> in <module>()
      1 with open("/Volumes/Thunderbay/CURRENT/Music/iTunes/iTunes Library.xml") as itl:
----> 2     library = plistlib.load(itl)
      3

/usr/local/Cellar/python3/3.4.3_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plistlib.py in load(fp, fmt, use_builtin_types, dict_type)
    984         fp.seek(0)
    985         for info in _FORMATS.values():
--> 986             if info['detect'](header):
    987                 P = info['parser']
    988                 break

/usr/local/Cellar/python3/3.4.3_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plistlib.py in _is_fmt_xml(header)
    556
    557     for pfx in prefixes:
--> 558         if header.startswith(pfx):
    559             return True
    560

TypeError: startswith first arg must be str or a tuple of str, not bytes

hmm ok, let's give it a hint:

In [3]: with open("/Volumes/Thunderbay/CURRENT/Music/iTunes/iTunes Library.xml") as itl:
    library = plistlib.load(itl, fmt=plistlib.FMT_XML)
   ...:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-ef5f06b44ec2> in <module>()
      1 with open("/Volumes/Thunderbay/CURRENT/Music/iTunes/iTunes Library.xml") as itl:
----> 2     library = plistlib.load(itl, fmt=plistlib.FMT_XML)
      3

/usr/local/Cellar/python3/3.4.3_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plistlib.py in load(fp, fmt, use_builtin_types, dict_type)
    995
    996     p = P(use_builtin_types=use_builtin_types, dict_type=dict_type)
--> 997     return p.parse(fp)
    998
    999

/usr/local/Cellar/python3/3.4.3_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plistlib.py in parse(self, fileobj)
    323         self.parser.EndElementHandler = self.handle_end_element
    324         self.parser.CharacterDataHandler = self.handle_data
--> 325         self.parser.ParseFile(fileobj)
    326         return self.root
    327

TypeError: read() did not return a bytes object (type=str)

plistlib is in the standard library, but from the problems above I have the feeling it has not actually been converted to Python 3?

Anyway, my actual question: is it possible to open an XML plist file with plistlib in Python 3.4.3?

surely I'm missing something obvious here perhaps... just noticed the Py2 version of plistlib (which works!) has a different interface, so someone has actually modified the code of the library for inclusion with Py3...

like image 426
Anentropic Avatar asked Jul 05 '15 18:07

Anentropic


1 Answers

Thanks to @J Presper Eckert for giving me a clue about what to look for...

I then found this article:
http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html#the-binary-option

which suggests the answer is simply to open the file in binary mode, tried it and it works!

with open("/Volumes/Thunderbay/CURRENT/Music/iTunes/iTunes Library.xml", 'rb') as itl:
    library = plistlib.load(itl)
like image 158
Anentropic Avatar answered Sep 21 '22 06:09

Anentropic