Omitting results with id3reader [Beginner]

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Wed Dec 5 08:12:22 EST 2007


Ionis a écrit :
> Hey guys, hope you can help me here. I've been playing with python for
> about a week or two and I've been reading "A Byte Of Python" to get me
> on my feet. I've decided to write a program which will list all ID3
> information in a directory of .mp3 files into a .html file.
> 
> The python script I'm using for this, along with album art (Example)
> are in the same directory as the music. The output I am getting when
> it reads these files is "None" so I tried to set up a way to get rid
> of these results and move onto the next file.
> 
> The omitting I'm attempting is within the If statement half way down
> the code, easy to find. Could anyone point me in the right direction
> on how to stop these "None" results showing in the result .html file.
> 
> Thanks in advance.
> 
> ==========
> import os
> import id3reader
> 
> songartist = str("")

You're passing a string to the string class constructor... this is a bit 
redondant, isn't it ?-)

songartist = ""

> songtrack = str("")
> html_bulkadd = str("")

idem...

> html_start = str("""
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
> www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
> <html xmlns="http://www.w3.org/1999/xhtml">
> 	<head>
> 		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
> 		<title>Test Document</title>
> 	</head>
> 	<body>
> """)
> html_end = str("""
>     </body>
> </html>
> """)


You may want to learn about string formating.

html_template = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
   www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
     <title>%(title)s</title>
   </head>
   <body>
     %(content)s
   </body>
</html>
"""
data = {'title':'The title',
         'content':"<h1>The content comes here</h1>\n"
                   + "<p>Fine, isn't it?</p>\n"
         }

print html_template % data


This would let you build the whole page in one pass instead...

> output = file("output.html", "w")
> output.write("")

??? Why this empty string ?

> output.write(html_start)
> output.close

This *doesn't* call the file.close method, but returns a reference to it 
(reference which is immediatly discarded). In Python, the parens are not 
optional wrt/ function call - in fact, they actually are the 'call' 
operator.

> path = ""

Note that you can pass arguments to Python scripts - like, say, a path. 
You retrieve the arg list in sys.argv:

import sys
try:
   # sys.argv[0] is either the script name or nothing,
   # depending on your os. The first arg - if there's one,
   # is sys.argv[1]
   path = sys.argv[1]
except IndexError:
   # no arg passed
   err = "usage : python myscript.py <path>\n(missing argument 'path')" \
   sys.exit(err)


then call it:

python myscript.py /path/to/some/mp3/dir

This would let you keep your script out of your music directory...


> dirList = os.listdir(path)

<ot>Usual convention is to use all_lower names for vars. </ot>

> for fname in dirList:
>     songartist = str("")
>     songtrack = str("")

Why do you rebind these 2 names ? There already defined above - and 
rebound below FWIW.

>     id3r = id3reader.Reader(fname)
>     if id3r.getValue('performer') == "None":

You want to test against the None object, not against the literal string 
"None":

      if id3.getValue("performer") is None:
         # etc

FWIW, note that id3.getValue(<tag here>) returning None doesn't mean the 
file is not a valid mp3 - just that it doesn't hold this information 
(tested here...). Anyway, Chris already told you a way to handle this 
problem...

>         break

This get you out of the loop, which may not be what you want. If you 
decide to ignore untagged mp3 files, using 'continue' might be a better 
idea.

>     elif id3r.getValue('title') == "None":
>         break

idem

>     else:
>         songartist = id3r.getValue('performer')
>         songtrack = id3r.getValue('title')

Since you only use these variables here, defining them at the top of 
your script, and rebiding them at the top of the loop is useless.

Also, you're making useless calls to id3r.getValue. A simpler solution 
would be to test the values *after* storing them:

for fname in dirList:
     # note that if your script is not in the same
     # directory as the one you're inspecting,
     # you need to pass absolute path:
     fpath os.path.join(path, fname)
     id3r = id3reader.Reader(fpath)
     songartist = id3r.getValue('performer')
     songtrack = id3r.getValue('title')
     if (songartist is None or songtrack is None):
        # if you want to just skip this file:
        continue
     # if you're here then songartist and songtrack are not None




>         output = file("output.html", "a")

Opening and closing files is a costly operation. You should not 
open/close a same file on each iteration - better to either keep it open 
or first store all data and only then open the file, write, and close.

Also and FWIW, you failed to properly close the file before the loop, 
and... (cf below)

>         output.write("<p>" + str(songartist) + " - " + str(songtrack)
> + "</p>\n")

songartist and songtrack are *already* strings.

>         output.close

(continued...) you still fail to close the file. For the record, the OS 
can only handle a given amount of opened files at once, so you may start 
to have IOErrors sometimes...


> output = file("output.html", "a")
> output.write("\n"+html_end)
> output.close

Same comments as above.


Here's a possible rewrite (nb: no tested, may need a couple fixes and 
has room for improvements). Feel free to ask for precisions about points 
you would not understand - but please try to find and read the relevant 
doc before !-)

# mp32html.py
import os
import sys
import glob
import id3reader

html_template = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <meta http-equiv="Content-Type"
           content="text/html; charset=utf-8" />
     <title>%(title)s</title>
   </head>
   <body>
     <h1>%(title)s</h1>
     %(content)s
   </body>
</html>
"""

file_template = "<li>%s - %s</li>"

usage = "python mp32html.py <path>"
try:
     path = sys.argv[1]
except IndexError:
     sys.exit(usage + "\nmissing argument <path>")

content = []
fnames = glob.glob(os.path.join(path, "*.mp3"))
for fname in fnames:
     id3r = id3reader.Reader(fname)
     songartist = id3r.getValue('performer')
     songtrack = id3r.getValue('title')
     if (songtrack is None or songartist is None):
         print >> sys.stderr, "no mp3 tags found in %s" % fname
         continue
     content.append(file_template % (songartist, songtrack))

if content:
     content = "<ul>\n%s</ul>\n" % "\n".join(content)
else:
     # content is empty, assume no (tagged) mp3 found
     content = "<em>No tagged mp3 found in %s</em>" % path

data = {
     'title': "mp3 listing for %s" % path,
     'content': content
     }

html = html_template % data

outpath = os.path.join(path, "output.html")
try:
     output = open(outpath, "w")
except IOError, e:
     err = "failed to open  file %s for writing : %s" % (outpath, e)
     sys.exit(err)

output.write(html)
output.close()




More information about the Python-list mailing list