Omitting results with id3reader [Beginner]

I

Ionis

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("")
songtrack = str("")
html_bulkadd = str("")
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">
<title>Test Document</title>
</head>
<body>
""")
html_end = str("""
</body>
</html>
""")

output = file("output.html", "w")
output.write("")
output.write(html_start)
output.close

path = ""
dirList = os.listdir(path)
for fname in dirList:
songartist = str("")
songtrack = str("")
id3r = id3reader.Reader(fname)
if id3r.getValue('performer') == "None":
break
elif id3r.getValue('title') == "None":
break
else:
songartist = id3r.getValue('performer')
songtrack = id3r.getValue('title')
output = file("output.html", "a")
output.write("<p>" + str(songartist) + " - " + str(songtrack)
+ "</p>\n")
output.close

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

If anyone is curious on the module you can find it here:
http://nedbatchelder.com/code/modules/id3reader.html
 
C

Chris

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("")
songtrack = str("")
html_bulkadd = str("")
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>
""")

output = file("output.html", "w")
output.write("")
output.write(html_start)
output.close

path = ""
dirList = os.listdir(path)
for fname in dirList:
songartist = str("")
songtrack = str("")
id3r = id3reader.Reader(fname)
if id3r.getValue('performer') == "None":
break
elif id3r.getValue('title') == "None":
break
else:
songartist = id3r.getValue('performer')
songtrack = id3r.getValue('title')
output = file("output.html", "a")
output.write("<p>" + str(songartist) + " - " + str(songtrack)
+ "</p>\n")
output.close

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

If anyone is curious on the module you can find it here:http://nedbatchelder.com/code/modules/id3reader.html

Untested code....

import os, fnmatch
for each_file in fnmatch.filter(os.listdir(path), '*.mp3'):
id3r = id3reader.Reader(each_file)
if id3r.getValue('performer') and id3r.getValue('title'):
output = open('output.html','ab')
output.write('<p>%s - %s</p>\n' % (id3r.getValue('performer'),
id3r.getValue('title')) )
output.close()
 
I

Ionis

Ok, just noticed you linked the id3reader. I tested my code and it
worked fine.

Thanks alot Chris. Could you comment your code so I can see what each
line is doing? I hope that isn't a problem. Still pretty new to python.
 
C

Chris

Thanks alot Chris. Could you comment your code so I can see what each
line is doing? I hope that isn't a problem. Still pretty new to python.

import os, fnmatch
""" fnmatch will check your directory listing and compare
it to the pattern, in this case mp3, and will normalize
the case for you as well and only return those matching
the pattern.
Equivalent commands would be: dir *.mp3 or ls *.mp3
"""
# os.listdir() and the fnmatch.filter will return you lists
# to iterate over so no need to store it seperately
for each_file in fnmatch.filter(os.listdir(path), '*.mp3'):
id3r = id3reader.Reader(each_file) # Read the new file
""" A value of None will return false if you test it so
by just doing 'if value', it will return false if
there is nothing.
"""
if id3r.getValue('performer') and id3r.getValue('title'):
output = open('output.html','ab')
# using string formatting is neater than string concatenation
output.write('<p>%s - %s</p>\n' % (id3r.getValue('performer'),
id3r.getValue('title')) )
output.close()

HTH,
Chris
 
B

Bruno Desthuilliers

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)

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

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()
 
I

Ionis

Thank you for your help, it is really appreciated. I'll post back if
there are any more problems.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,631
Members
45,338
Latest member
41Pearline46

Latest Threads

Top