• Welcome to Valhalla Legends Archive.
 

Getting Cozy With Python

Started by shadypalm88, March 15, 2006, 08:59 PM

Previous topic - Next topic

shadypalm88

So I've started to learn Python, and the first thing I've used it for is to write a script that flips through an exported iTunes library (XML, linked file is quite big) and outputs a list of all artists found in the library.  It is supposed to only print an artist once, no matter how many times it appears in the file, and no matter the case in which the artist name is recorded.

If anyone familiar with the language could look through it and offer suggestions as to how it could be made more "pythonic", I'd greatly appreciate it.

from xml.dom.minidom import parse

class iTunesError (Exception):

def __init__(self, message):
self.message = message
pass

class iTunesLibrary (object):

def __init__(self, file):
self.xml = parse(file)
self.tracks = []
self.process()
pass

def process(self):
plist = self.xml.documentElement
if (plist.nodeName != u'plist'):
raise iTunesError("Invalid XML file.")
if (plist.attributes['version'].value != u'1.0'):
raise iTunesError("Invalid property list version.")

dct = False
for el in plist.childNodes:
if (el.nodeType == 1 and el.nodeName == u'dict'):
dct = el
break
else:
raise iTunesError("No master dictionary found.")

tracks = False
for el in dct.childNodes:
if (el.nodeType == 1 and el.nodeName == u'key' and
el.firstChild.nodeValue == u'Tracks'):
tracks = el.nextSibling
while (tracks.nodeType != 1):
tracks = tracks.nextSibling
break
else:
raise iTunesError("No track list found.")

for el in tracks.childNodes:
if el.nodeType != 1 or el.nodeName != u'dict':
continue
self.tracks += [self.processTrack(el)]

def processTrack(self, track):
key = False
t = {}
for el in track.childNodes:
if el.nodeType != 1:
continue
if el.nodeName == u'key':
key = el.firstChild.nodeValue.lower()
else:
if el.nodeName == u'true':
t[key] = True
elif el.nodeName == u'false':
t[key] = False
else:
t[key] = el.firstChild.nodeValue
return t

if __name__ == '__main__':
import sys
lib = iTunesLibrary(sys.argv[1])
artists = {}
for track in lib.tracks:
try:
artist = track[u'artist']
fixed = artist.lower()
artists[fixed] = artist
except KeyError:
pass

artist_list = artists.values()
artist_list.sort()
for artist in artist_list:
print artist

Banana fanna fo fanna

Hey there,

You might want to check out a very Pythonic XML library which will be going in to Python 2.5's standard library, ElementTree (www.effbot.org). You also might want to check out a piece of code that I integrated into one of my old demo projects: http://subway.python-hosting.com/file/crackajax/trunk/ituneslib.py

Yegg

pass is simply a placeholder, don't use it under iTunesError's or iTunesLibrary's constructor. Where you used it under except KeyError is fine. Why are you trying to use Unicode with so many strings? Also, when doing numeric comparison, you can also use is as opposed to ==. Other than that everything seems to be pretty good.

shadypalm88

Quote from: Banana fanna fo fanna on March 16, 2006, 02:25 PM
Hey there,

You might want to check out a very Pythonic XML library which will be going in to Python 2.5's standard library, ElementTree (www.effbot.org). You also might want to check out a piece of code that I integrated into one of my old demo projects: http://subway.python-hosting.com/file/crackajax/trunk/ituneslib.py
Cool, thanks.

Quote from: Yegg on March 16, 2006, 05:00 PM
pass is simply a placeholder, don't use it under iTunesError's or iTunesLibrary's constructor.
Leftover piece I didn't notice from my text editor's snippet for a new-style class; forgot to remove it.  Thanks.
Quote from: Yegg on March 16, 2006, 05:00 PMWhy are you trying to use Unicode with so many strings?
I used the interactive mode of the interpreter to play around with the DOM library and it returns all Unicode strings, so I used them to prevent conversions.
Quote from: Yegg on March 16, 2006, 05:00 PMAlso, when doing numeric comparison, you can also use is as opposed to ==. Other than that everything seems to be pretty good.
Thanks.