Valhalla Legends Forums Archive | General Programming | Getting Cozy With Python

AuthorMessageTime
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.

[code]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[/code]
March 16, 2006, 2:59 AM
St0rm.iD
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
March 16, 2006, 8:25 PM
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.
March 16, 2006, 11:00 PM
shadypalm88
[quote author=Banana fanna fo fanna link=topic=14521.msg148500#msg148500 date=1142540728]
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
[/quote]Cool, thanks.

[quote author=Yegg link=topic=14521.msg148506#msg148506 date=1142550008]
pass is simply a placeholder, don't use it under iTunesError's or iTunesLibrary's constructor.[/quote]Leftover piece I didn't notice from my text editor's snippet for a new-style class; forgot to remove it.  Thanks.[quote author=Yegg link=topic=14521.msg148506#msg148506 date=1142550008]Why are you trying to use Unicode with so many strings?[/quote]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 author=Yegg link=topic=14521.msg148506#msg148506 date=1142550008]Also, when doing numeric comparison, you can also use is as opposed to ==. Other than that everything seems to be pretty good.
[/quote]Thanks.
March 17, 2006, 1:25 PM

Search