Mailing List Archive

Testing if a variable is an integer or a string; exceptions in __del__
I'm brand spanking new to Python, but I couldn't find an answer to
this in the tutorial or the FAQ.

I'm writing a module to manipulate Id3 tags on mp3 files; I've gotten
it pretty much done, but there are some sections of the code I'm
unsatisfied with, as this is my very first Python code I've written.

My first question is:

What's the best way to test if a variable is numeric or a string?
I'd like to be able to test my Id3 module with some command-line
options, one of which denotes the genre of the file.

The genre can either be an integer from 0 to 254 or a string. As
it is, I'm using

if re.match('^\d+$', options['genre']):

to test if the option is an integer or not. Is this the best way to do
it?

Next:

I'm running Python 1.5.1; it seems that in these later versions, if an
exception is thrown in an object's __del__ method, a warning is
printed to STDOUT. However, this warning is not terribly helpful.

My Id3 class originally had a small bug in it, where a certain value
that the destructor tested would not be initialized if an IOError
exception occurred in the constructor. When it had this bug, a bizarre
looking warning was printed when the __del__ method tried to access
this uninitialized variable:

Exception exceptions.AttributeError: <exceptions.AttributeError
instance at 80cd930> in <method Id3.__del__ of Id3 instance at
80cd738> ignored

Is there any way to get these __del__ exception warnings to be a
little more, well, verbose?

As it is, this completely worthless to me as a debugging tool. I
eventually figured out what my problem was, but it would have been a
lot clearer if it had told me I had an uninitialized variable instead
of an exceptions.AttributeError with a nice message of
<exceptions.AttributeError instance at 80cd930>! It didn't even tell
me what line my problem was on. Sheesh.

Finally:

When this module is done, I'd love to submit it to the Python
community so everyone can have an interface to manipulating Id3 tags
on MP3 files. What's the accepted way of doing this? Is there an
equivalent of Perl's CPAN for Python?

Thanks,

Ben

--
Brought to you by the letters E and S and the number 14.
"It's all just a little bit of history repeating."
Debian GNU/Linux maintainer of Gimp and GTK+ -- http://www.debian.org/
I'm on FurryMUCK as Che, and EFNet/Open Projects IRC as Che_Fox.
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
[Ben Gertzfield]
> ...
> What's the best way to test if a variable is numeric or a string?
> ...
> The genre can either be an integer from 0 to 254 or a string. As
> it is, I'm using
>
> if re.match('^\d+$', options['genre']):
>
> to test if the option is an integer or not. Is this the best way to do
> it?

It's *a* way to do it. Does something about it bother you? If you're just
seeking variety, e.g. here's another way

try:
int(thing)
lookslikeanint = 1
except:
lookslikeanint = 0

That's much easier to extend if you want to ensure that the integer value
truly is "from 0 to 254".

> ...
> I'm running Python 1.5.1; it seems that in these later versions, if an
> exception is thrown in an object's __del__ method, a warning is
> printed to STDOUT. However, this warning is not terribly helpful.
> ...
> Exception exceptions.AttributeError: <exceptions.AttributeError
> instance at 80cd930> in <method Id3.__del__ of Id3 instance at
> 80cd738> ignored

"exception ignored" msgs are unique to exceptions raised at system shutdown
time, when the order of module content destruction can't magically ensure
that whatever the heck you happen to reference in your __del__ methods still
exists at the time __del__ is called. Since the system is shutting down, it
has no choice but to ignore these exceptions and carry on regardless.

If you're not getting this msg at shutdown time, it's a bug and you should
post a minimal failing example.

If you are getting this msg at shutdown time, the cruel-but-fair short
answer is "tough": the system *is* shutting down, and is severely limited
in what it can do in response to exceptions given that huge portions of the
runtime have gone missing <wink>.

> ...
> When this module is done, I'd love to submit it to the Python
> community so everyone can have an interface to manipulating Id3 tags
> on MP3 files.

Get familiar with

http://www.python.org/download/Contributed.html
and
http://www.python.org/ftp/python/contrib/

> What's the accepted way of doing this? Is there an equivalent of Perl's
> CPAN for Python?

Afraid not -- not even close. There are various collections and "guides"
scattered all over the place, and whenever I mention this some one or two
people reply outraged that I didn't name theirs specifically; then someone
else chimes in to repeat that someday Python will have a scheme *better*
than CPAN. So, like I said, not even close <wink>.

although-someday-etc-ly y'rs - tim
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
>>>>> "Tim" == Tim Peters <tim_one@email.msn.com> writes:

Ben> What's the best way to test if a variable is numeric or a string?
Ben> if re.match('^\d+$', options['genre']):

Tim> It's *a* way to do it. Does something about it bother you?

No, I was just wondering if there was a more standard Pythonesque
way of doing it.

It seems like a rather common thing to do, is why I asked. :)

I guess my way works fine. I was thinking in Perl terms, which
ended up working well.

Tim> "exception ignored" msgs are unique to exceptions raised at
Tim> system shutdown time, when the order of module content
Tim> destruction can't magically ensure that whatever the heck you
Tim> happen to reference in your __del__ methods still exists at
Tim> the time __del__ is called. Since the system is shutting
Tim> down, it has no choice but to ignore these exceptions and
Tim> carry on regardless.

Ah, okay. So what I should have done was put the work done by __del__
in another function and tested that *before* system shutdown time.

Makes sense. Although I wish the messages were just a tiny bit more
helpful!

Ben> When this module is done, I'd love to submit it to the Python
Ben> community so everyone can have an interface to manipulating Id3 tags
Ben> on MP3 files.

Tim> Get familiar with

Tim> http://www.python.org/download/Contributed.html
Tim> and
Tim> http://www.python.org/ftp/python/contrib/

Okay. Too bad there isn't a more organized way of doing it.

Thanks!

Ben

--
Brought to you by the letters Y and A and the number 1.
"Two thousand people in a seething, roaring, shouting mass."
Debian GNU/Linux maintainer of Gimp and GTK+ -- http://www.debian.org/
I'm on FurryMUCK as Che, and EFNet/Open Projects IRC as Che_Fox.
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
To answer your specific question specifically, re.match isn't a great
way to test if the input is an integer. In Perl, regular expressions
are a Swiss army knife of sorts -- handy in all sorts of situations.
In Python, you'll find them most handy from string processing (and
even then you'll find that sometimes plain old string.split will do).

A more Pythonic way to check if a string is an integer is to try to
convert it to an integer using string.atoi and then catching the
exception.

try:
self.year = string.atoi(buf[90:94])
except ValueError:
self.year = 0

string.atoi raises a ValueError when passed something like 'Funk', but

watch out for negative numbers.

Another option, since you'll have to convert the genre names to
integers in order to encode them in the mp3 tag anway, is to use the
dictionary that maps genre names to integers. Let's assume genre_dict
is the dictionary and genre_inp is what the user typed.

if genre_dict.has_key(genre_inp):
genre = genre_dict[genre_inp]
else:
try:
genre = string.atoi(genre_inp)
except ValueError:
raise ValueError, "Invalid genre: %s" % genre_inp

Now genre will be the numeric genre value.

Jeremy
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
Interesting. :) Aren't using exceptions a lot of overhead, though?

--
Brought to you by the letters K and J and the number 0.
"A yonker is a young man."
Debian GNU/Linux maintainer of Gimp and GTK+ -- http://www.debian.org/
I'm on FurryMUCK as Che, and EFNet/Open Projects IRC as Che_Fox.
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
Ben Gertzfield <che@debian.org> wrote:
>What's the best way to test if a variable is numeric or a string?
>I'd like to be able to test my Id3 module with some command-line
>options, one of which denotes the genre of the file.

and later he wrote:

> Aren't using exceptions a lot of overhead, though?

not if they're not raised. and I doubt that you'll
notice the difference in this case...

(premature optimisation is the root etc etc)

here's one optimization you might wish to consider,
though: use "int" instead of "string.atoi" (that'll save
you 8 keystrokes!)

</F>
Testing if a variable is an integer or a string; exceptions in __del__ [ In reply to ]
>>>>> "Fredrik" == Fredrik Lundh <fredrik@pythonware.com> writes:

Fredrik> here's one optimization you might wish to consider,
Fredrik> though: use "int" instead of "string.atoi" (that'll save
Fredrik> you 8 keystrokes!)

*chuckle* Thanks.

--
Brought to you by the letters P and X and the number 13.
"Do you wish to see our *surprising toys*? No! Do not!"
Debian GNU/Linux maintainer of Gimp and GTK+ -- http://www.debian.org/
I'm on FurryMUCK as Che, and EFNet/Open Projects IRC as Che_Fox.