Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

subclassing Exceptions

0 views
Skip to first unread message

Sheila King

unread,
Jul 21, 2001, 11:20:46 PM7/21/01
to
OK, I've become fairly comfortable with defining my own classes and
subclassing other classes and so on...

Now I'm wanting to create some of my own exceptions. I've searched
comp.lang.python at Google Groups, and the archives for the Tutor list,
and faqts.python.com and my copy of Core Python Programming, but all I
find on the subject is essentially this:

"""

You can create a new exception by subclassing one of the standard
exceptions like this:

class MyNewException(SomeStandardException):
pass


Just use the 'pass' statement unless you want to override some of the
methods/data of the Standard Exception.

"""

And that's all the information I can find.

I tried looking under the /Python20 directory for source or something
for the Exception classes, but can't find it. For example, right now I'm
working on subclassing the rfc822.py module, and I found the file
rfc822.py in /Python20/Lib and studied the source until I understood it,
and could subclass it. I'd like to find something similar for the
standard exception classes. I looked in the /include directory and some
others but can't find what I'm needing.

Thanks for any pointers/tips.

--
Sheila King
http://www.thinkspot.net/sheila/
http://www.k12groups.org/


Brian Quinlan

unread,
Jul 21, 2001, 11:49:01 PM7/21/01
to Sheila King, pytho...@python.org
> I tried looking under the /Python20 directory for source or something
> for the Exception classes, but can't find it. For example, right now
I'm
> working on subclassing the rfc822.py module, and I found the file
> rfc822.py in /Python20/Lib and studied the source until I understood
it,
> and could subclass it. I'd like to find something similar for the
> standard exception classes. I looked in the /include directory and
some
> others but can't find what I'm needing.
>
> Thanks for any pointers/tips.

Check out http://www.python.org/doc/current/lib/module-exceptions.html

Cheers,
Brian


Sheila King

unread,
Jul 22, 2001, 12:44:44 AM7/22/01
to
On Sat, 21 Jul 2001 20:49:01 -0700, "Brian Quinlan" <br...@sweetapp.com>
wrote in comp.lang.python in article
<mailman.995773776...@python.org>:

:> I tried looking under the /Python20 directory for source or something


:> for the Exception classes, but can't find it. For example, right now
:> I'm working on subclassing the rfc822.py module, and I found the file
:> rfc822.py in /Python20/Lib and studied the source until I understood
:> it, and could subclass it. I'd like to find something similar for the
:> standard exception classes. I looked in the /include directory and
:> some others but can't find what I'm needing.

:
:Check out http://www.python.org/doc/current/lib/module-exceptions.html
:

Thanks, Brian, but I've seen the docs many times. I need more info than
that. Like example code, or source code.

However, someone else gave me some pointers.

If I want to see the actual source for the exceptions.c class, I can
browse at sourceforge.net here:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/python/dist/src/

I found the exceptions.c file here:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/python/dist/src/Python/exceptions.c

However, I may not need that much detail and background. Maybe a few
examples of subclassing exceptions in Python would do. So, one might
want to look at these:

See the source for this module:
http://python.org/doc/current/lib/module-xml.sax.html
(although, later thought to possibly be a bit complicated)

or

How about viewing the source for the ConfigParser.py module.

Anyhow, I've looked a bit over the exceptions.c file, which is
interesting. Now I'm off to study the source for the (above) suggested
Python modules, as examples of subclassing exceptions.

Volucris

unread,
Jul 22, 2001, 1:51:31 AM7/22/01
to
If all you want is your own exception (nothing fancy), all you need is a
class:

class SpamException:
pass

you can raise and catch that just like any exception, but it'll be kind of
ugly when it gets printed.

class SpamException:
def __str__(self):
return "cooking spam is not required"

that will give a clue as to what the exception means. That said, I don't
recall ever seeing an exception not subclassed from Exception, so it's
probably a good idea.

class SpamException(Exception):
def __str__(self):
return "cooking spam is not required"

I don't know why every one is subclassed, but the HPIC seem to know what
they're doing so far. I have no reason to question them. Yet.

--

Volucris (a) hotmail.com
"Eu não falo uma única palavra do português."

"Sheila King" <she...@spamcop.net> wrote in message
news:9ihklt8u0vvh1aa0m...@4ax.com...

Sheila King

unread,
Jul 22, 2001, 2:20:14 AM7/22/01
to
On Sun, 22 Jul 2001 00:51:31 -0500, "Volucris" <volu...@hotmail.com>

wrote in comp.lang.python in article
<3b5a69a3$0$320$6e49...@news.goldengate.net>:

:If all you want is your own exception (nothing fancy), all you need is a
:class:
:
:class SpamException:
: pass

OK, interesting. I didn't realize you could make an exception without
subclassing it. So, I tried this script:

-----------begin except.py---------------------

class SpamException:
pass

while (1):
inputstring = raw_input("Enter any string, except 'spam': ")
if inputstring == "spam":
raise SpamException

-----------end except.py-----------------------

Here is a sample output:

>>>
Enter any string, except 'spam': pig
Enter any string, except 'spam': spam
Traceback (innermost last):
File "E:/programs/LearningPython/Exceptions/except.py", line 7, in ?
raise SpamException
SpamException: <__main__.SpamException instance at 0104C94C>


:you can raise and catch that just like any exception, but it'll be kind of


:ugly when it gets printed.

Well, yes. It doesn't look like normal exceptions, does it?

:class SpamException:


: def __str__(self):
: return "cooking spam is not required"
:
:that will give a clue as to what the exception means.

OK, so I modified my above file, to include the __str__ as you show.
Here is a sample run:

>>>
Enter any string, except 'spam': horse
Enter any string, except 'spam': meat
Enter any string, except 'spam': spam
Traceback (innermost last):
File "E:/programs/LearningPython/Exceptions/except.py", line 8, in ?
raise SpamException
SpamException: cooking spam is not required

So, yes, it does look a bit nicer.

:That said, I don't


:recall ever seeing an exception not subclassed from Exception, so it's
:probably a good idea.
:
:class SpamException(Exception):
: def __str__(self):
: return "cooking spam is not required"
:
:I don't know why every one is subclassed, but the HPIC seem to know what
:they're doing so far. I have no reason to question them. Yet.

Interesting point. When I make this modification to the SpamException
class, deriving it from the Exception class, I seem to get the exact
same behavior.

However, I noticed earlier this evening, from browsing the exceptions.c
source (as noted elsewhere in this thread), that the Exceptions seem to
have 3 methods and 1 datamember, namely:

methods:
__init__
__getitem__
__str__

and the datamember
__doc__

So, I would imagine that if you subclass it, and do not specifically
define these methods/data listed above, that you at least inherit them
from the base class. Whereas, if you create an "exception" that does not
derive from a base Exception class, it would not have these methods.


Hmm...I just tried a little experiment in the interactive shell to see
if I could confirm/deny my above theory, and it gave me surprising
results that I do not understand, and which seem to indicate no
difference between deriving it from an Exception class or not.

Well, I am interested in further enlightenment on this topic...?

Tom Bryan

unread,
Jul 21, 2001, 10:46:25 PM7/21/01
to
Sheila King wrote:

> On Sun, 22 Jul 2001 00:51:31 -0500, "Volucris" <volu...@hotmail.com>
> wrote in comp.lang.python in article
> <3b5a69a3$0$320$6e49...@news.goldengate.net>:
>
> :If all you want is your own exception (nothing fancy), all you need is a
> :class:
> :
> :class SpamException:
> : pass
>
> OK, interesting. I didn't realize you could make an exception without
> subclassing it. So, I tried this script:

Neither did I, but you probably don't want to do that.

One reason to subclass from a common Exception base class is so
that exceptions can be caught based on inheritence. Also, since
there's a common exception base class, all exceptions have common
behavior that you'd have to recode if you didn't subclass.

> Hmm...I just tried a little experiment in the interactive shell to see
> if I could confirm/deny my above theory, and it gave me surprising
> results that I do not understand, and which seem to indicate no
> difference between deriving it from an Exception class or not.

Consider:

----- test1.py -----
class SpamException:
pass

try:


while (1):
inputstring = raw_input("Enter any string, except 'spam': ")
if inputstring == "spam":
raise SpamException

# Catch *all* exceptions...
# at least those that subclass Exception like they should. :-)
except Exception, data:
print "Ahhh! ", data
-----------------

If I run this, the except block is unable to catch SpamException,
although it looks like I should be catching all exceptions since I'm
catching the base class of all exceptions:

Enter any string, except 'spam': spam

Traceback (most recent call last):
File "test_exception.py", line 11, in ?
raise SpamException
__main__.SpamException: <__main__.SpamException instance at 0x80d6cb4>

----- test2.py -----
class SpamException(Exception):
pass

try:


while (1):
inputstring = raw_input("Enter any string, except 'spam': ")
if inputstring == "spam":

raise SpamException( 'User typed "spam."' )
# Catch *all* exceptions...
# at least those that subclass Exception like they should. :-)
except Exception, data:
print "Ahhh! ", data
----------------

Since I sublcass Exception, the except block will be able to catch my
exception, and the SpamException automatically gets a constructor
that takes an error message as an argument. See:

Enter any string, except 'spam': spam

Ahhh! User typed "spam."

> Well, I am interested in further enlightenment on this topic...?

I believe that the intent is for all exception classes to subclass from
Exception or one of its sublcasses. I think that a common idiom is for
a module to declare its own base exception class. Then, it can declare
many subclasses of *that* Exception subclass to use internally. People
using the module can simply catch the base FooException unless they
have a good reason to get more specific. Basically, they called code
in your module, and it blew up. Often, that's as much as they can say,
and the error message attached to the exception *should be* enlightening
enough to troubleshoot the problem.

For example,

class StackException( Exception ):
pass
class EmptyStackException( StackException ):
pass
class StackOverflowException( StackException ):
pass

class Stack:
"""An implementation of the Stack data structure
that supports a maximum stack stize. """
def __init__( self, maxSize=None ):
try:
self.stack = []
self.max = int( maxSize )
except ValueError:
#value error is thrown when maxSize isn't an integer
raise StackException( "Illegal value for Stack's maximum size: %s." % maxSize )
def push( self, data ):
if self.max != None and len(self.stack) == self.max:
raise StackOverflowException( "Stack already at maximum size %d" % self.max )
self.stack.append( data )
def pop( self ):
if len( self.stack ) == 0:
raise EmptyStackException( "Cannot pop from an empty stack" )
self.stack, data = self.stack[:-1], self.stack[-1]
return data
def peek( self ):
if len( self.stack ) == 0:
raise EmptyStackException( "Cannot peek at an empty stack" )
return self.stack[ -1 ]

if __name__ == '__main__':
# Note that our code can simply catch the StackException base class
try:
aStack = Stack( 'hi' )
except StackException, data:
print "Exception for Stack('hi'):", data

try:
aStack = Stack( 2 )
print aStack.peek()
except StackException, data:
print "Exception for aStack.peek():", data

try:
print aStack.pop()
except StackException, data:
print "Exception for aStack.pop():", data

try:
aStack.push( 'one' )
aStack.push( 'two' )
aStack.push( 'three' )
except StackException, data:
print "Exception for aStack.push('three'):", data


Of course, this advice might be slightly off. Python's exception stuff looks
a lot like the Java exception stuff, and I've done a lot more Java.

Exception-"too-many-languages"-ly yours
---Tom

Erik Max Francis

unread,
Jul 22, 2001, 1:55:10 PM7/22/01
to
Sheila King wrote:

> Thanks, Brian, but I've seen the docs many times. I need more info
> than
> that. Like example code, or source code.

The library reference quoted states pretty clearly:

The root class for exceptions. All built-in exceptions are
derived from this class. All user-defined exceptions should
also be derived from this class, but this is not (yet) enforced.
The str() function, when applied to an instance of this
class (or most derived classes) returns the string value of the
argument or arguments, or an empty string if no
arguments were given to the constructor. When used as a
sequence, this accesses the arguments given to the
constructor (handy for backward compatibility with old code).
The arguments are also available on the instance's args
attribute, as a tuple.

This gives you a pretty effective specification for what a class derived
from exceptions.Exception should do; it should return something
meaningful in its __str__ method, support __len__ and __getitem__ for
indexing, and have an `args' attribute that contains the arguments it
was instantiated with as a tuple.

The Exception class itself does this. If all you want is a different
_type_ of exception that you can key off of, then deriving from the
class and doing nothing with it (using `pass' as you did in your
example) is perfectly satisfactory. If you want to do more, then you
can add extra methods as you need that use the value gained through
calling `str' or the `args' attribute.

What more did you need to know?

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ But since when can wounded eyes see / If we weren't who we were
\__/ Joi
Rules for Buh / http://www.alcyone.com/max/projects/cards/buh.html
The official rules to the betting card game, Buh.

Erik Max Francis

unread,
Jul 22, 2001, 2:00:28 PM7/22/01
to
Sheila King wrote:

> OK, interesting. I didn't realize you could make an exception without
> subclassing it.

You can, but the library reference (2.2, Built-in Exceptions) states
that user-defined exceptions _should_ be derived from
exceptions.Exception, and suggests that this behavior might be enforced
in the future. It's generally good practice.

> However, I noticed earlier this evening, from browsing the
> exceptions.c
> source (as noted elsewhere in this thread), that the Exceptions seem to
> have 3 methods and 1 datamember, namely:
>
> methods:
> __init__
> __getitem__
> __str__
>
> and the datamember
> __doc__

And an `args' method, as the library reference states:

Python 2.0 (#2, Apr 4 2001, 19:28:30)
[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> try:
... raise Exception
... except Exception, e:
... pass
...
>>> dir(e)
['args']

> So, I would imagine that if you subclass it, and do not specifically
> define these methods/data listed above, that you at least inherit them
> from the base class. Whereas, if you create an "exception" that does
> not
> derive from a base Exception class, it would not have these methods.

Correct. A class you intend to use for exceptions is just like any
other class; there's nothing special about it. Only when you derive
from exceptions.Exception does it make it clear you plan to use the
class for exception handling, and since you derive from the Exception
class you get standard behavior for free even if you do not extend it.

> Hmm...I just tried a little experiment in the interactive shell to see
> if I could confirm/deny my above theory, and it gave me surprising
> results that I do not understand, and which seem to indicate no
> difference between deriving it from an Exception class or not.

Well, if you don't understand the results, it's going to be a little
hard telling you what you did wrong or what you misunderstood without
knowing what you actually did. :-)

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ History is a bucket of ashes.
\__/ Carl Sandburg
Erik Max Francis' bookmarks / http://www.alcyone.com/max/links/
A highly categorized list of Web links.

Sheila King

unread,
Jul 22, 2001, 2:23:21 PM7/22/01
to
On Sun, 22 Jul 2001 07:46:25 +0500, Tom Bryan <tbr...@python.net> wrote
in comp.lang.python in article <9jee61$2ac$1...@slb6.atl.mindspring.net>:

:Sheila King wrote:
:
:> OK, interesting. I didn't realize you could make an exception without


:> subclassing it. So, I tried this script:
:
:Neither did I, but you probably don't want to do that.

Right.

:One reason to subclass from a common Exception base class is so

:that exceptions can be caught based on inheritence. Also, since
:there's a common exception base class, all exceptions have common
:behavior that you'd have to recode if you didn't subclass.

You know, late last night/early this morning, that just kind of slipped
past me. But it makes perfect sense (of course).

:> Well, I am interested in further enlightenment on this topic...?


:
:I believe that the intent is for all exception classes to subclass from
:Exception or one of its sublcasses. I think that a common idiom is for
:a module to declare its own base exception class. Then, it can declare
:many subclasses of *that* Exception subclass to use internally. People
:using the module can simply catch the base FooException unless they
:have a good reason to get more specific. Basically, they called code
:in your module, and it blew up. Often, that's as much as they can say,
:and the error message attached to the exception *should be* enlightening
:enough to troubleshoot the problem.

Thanks. This is exactly the type of stuff that I am currently working
with and need to know about.

:For example,

[excellent code for stack class with exceptions, snipped]

:Of course, this advice might be slightly off. Python's exception stuff looks

:a lot like the Java exception stuff, and I've done a lot more Java.

It looked awfully good to me. I'm subclassing some of the mail modules,
like rfc822 right now, and also another project working with RGB vs. Hex
color values and the correct way of writing my own Exceptions for these
modules has been preventing me from getting very far into it, since I
keep pausing and wondering how to handle it, and my overview of the
entire module is affected by how I want to handle this.

Thanks,

Sheila King

unread,
Jul 22, 2001, 2:36:07 PM7/22/01
to
On Sun, 22 Jul 2001 10:55:10 -0700, Erik Max Francis <m...@alcyone.com>
wrote in comp.lang.python in article <3B5B137E...@alcyone.com>:

I'm trying to see the "big picture". I'm a "big picture" kind of gal. I
don't feel comfortable working with just bits and pieces...just enough
information (in the information-giver's opinion) for me to get by.

If I want to really understand subclassing Exceptions, and whether or
not I would ever want to override any of the standard exception classes
methods or such, then I need to understand how those exceptions work.

Like I said, I've been working (a bit) so far with subclassing
rfc822.py, and for me, I needed to read the source code of that module
and see how it worked. Then *bing* a light went off in my head, I
understood, and I could proceed.

Does this mean there is something wrong with me? Should I be satisfied
with the docs only?

Someone else gave me a good suggestion on the Tutor List, that if I was
really interested in how the Exception class works, I should grab the
source for Python 1.5.2, before the exception class code was written in
C. I might do that, but this discussion (and another on the Tutor List)
has helped immensely, and I may be fine from here.

Erik Max Francis

unread,
Jul 22, 2001, 3:18:17 PM7/22/01
to
Sheila King wrote:

> I'm trying to see the "big picture". I'm a "big picture" kind of gal.
> I
> don't feel comfortable working with just bits and pieces...just enough
> information (in the information-giver's opinion) for me to get by.

...


> Does this mean there is something wrong with me? Should I be satisfied
> with the docs only?

Not necessarily, but I'm still not sure what you're asking for. You say
you want the "big picture," but your queries seem too general to pin
down exactly what part of the "big picture" (if any) you're missing,
particularly since you have access to and have read the library
reference section on exceptions.Exception.

Why not try asking some very specific questions, with code if necessary,
and see where that takes you?

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Humor is emotional chaos remembered in tranquility.
\__/ James Thurber

Quinn Dunkan

unread,
Jul 22, 2001, 4:26:41 PM7/22/01
to
On Sun, 22 Jul 2001 18:36:07 GMT, Sheila King <she...@spamcop.net> wrote:
>I'm trying to see the "big picture". I'm a "big picture" kind of gal. I
>don't feel comfortable working with just bits and pieces...just enough
>information (in the information-giver's opinion) for me to get by.
>
>If I want to really understand subclassing Exceptions, and whether or
>not I would ever want to override any of the standard exception classes
>methods or such, then I need to understand how those exceptions work.
>
>Like I said, I've been working (a bit) so far with subclassing
>rfc822.py, and for me, I needed to read the source code of that module
>and see how it worked. Then *bing* a light went off in my head, I
>understood, and I could proceed.
>
>Does this mean there is something wrong with me? Should I be satisfied
>with the docs only?
>
>Someone else gave me a good suggestion on the Tutor List, that if I was
>really interested in how the Exception class works, I should grab the
>source for Python 1.5.2, before the exception class code was written in
>C. I might do that, but this discussion (and another on the Tutor List)
>has helped immensely, and I may be fine from here.

Yeah, go find exception.py. You'll probably realize that you knew the big
picture all along: exceptions are just normal instances of normal classes, and
they "work" exactly the same. They have a few __getitem__ and __str__ hacks
to be compatible from when exceptions were just strings (and maybe tuples),
but they're just normal classes. You can subclass Exception if you want, all
that means is a) you inherit Exception's methods, and b) 'except Exception'
will catch your exception. Or you could not inherit. Or you could raise some
random other object (not recommended, though). Exceptions are instantiated
and used just like any other object:

class Foo:
def __init__(self, x, y, z=10):
self.x, self.y, self.z = x, y, z
def foo(self):
print self.x

try:
raise Foo(10, 4, z=40)
except Foo, e:
print e.z
e.foo()

# let's be perverse:
try:
import smtplib
raise smtplib.SMTP('foo.com')
except smtplib.SMTP, s:
s.sendmail('me', ['you'], 'hi')
s.close()


etc.

This also raises the question: when types and classes are unified, will you be
able to raise anything?

Sheila King

unread,
Jul 22, 2001, 5:14:55 PM7/22/01
to
On Sun, 22 Jul 2001 12:18:17 -0700, Erik Max Francis <m...@alcyone.com>
wrote in comp.lang.python in article <3B5B26F9...@alcyone.com>:

:Sheila King wrote:
:
:> I'm trying to see the "big picture". I'm a "big picture" kind of gal.
:> I don't feel comfortable working with just bits and pieces...just enough
:> information (in the information-giver's opinion) for me to get by.
: ...
:> Does this mean there is something wrong with me? Should I be satisfied
:> with the docs only?
:
:Not necessarily, but I'm still not sure what you're asking for. You say
:you want the "big picture," but your queries seem too general to pin
:down exactly what part of the "big picture" (if any) you're missing,
:particularly since you have access to and have read the library
:reference section on exceptions.Exception.

That's because the "big picture" is the general overview of how the
parent class works. It is a general question, which is why I wanted to
see the source for the class (which is all I originally asked for...a
pointer to the source files...and that question has since been
answered.) Actually, I just downloaded the source for 1.5.2 and am
looking at exceptions.py and am finding it quite enlightening.

This is silly. I'm defending asking to see the source code. ????

:Why not try asking some very specific questions, with code if necessary,


:and see where that takes you?

Believe me, when I get some specific questions I will ask them. I'm sure
there is no shortage of specific questions from me on this list or on
the tu...@python.org list, either.

Erik Max Francis

unread,
Jul 22, 2001, 5:21:10 PM7/22/01
to
Sheila King wrote:

> That's because the "big picture" is the general overview of how the
> parent class works.

The behavior of the parent class is as the library reference states: It
implements __str__, __getitem__, __len__ (presumably), and args.
Exception is just a class like everything else; other than having the
behavior as specified in the reference, it's your typical class.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Sanity is a cozy lie.
\__/ Susan Sontag
The laws list / http://www.alcyone.com/max/physics/laws/
Laws, rules, principles, effects, paradoxes, etc. in physics.

Tim Peters

unread,
Jul 22, 2001, 6:08:09 PM7/22/01
to pytho...@python.org
[Sheila King]
> ...

> That's because the "big picture" is the general overview of how the
> parent class works. It is a general question, which is why I wanted to
> see the source for the class (which is all I originally asked for...a
> pointer to the source files...and that question has since been
> answered.) Actually, I just downloaded the source for 1.5.2 and am
> looking at exceptions.py and am finding it quite enlightening.
>
> This is silly. I'm defending asking to see the source code. ????

You don't have to defend yourself -- Guido will do it for you <wink>. He
opened a bug report on SourceForge today:

#443559 creating exceptions is underdocumented

and attached one of your first msgs as evidence. This area is indeed
"underdocumented".


Sheila King

unread,
Jul 22, 2001, 9:59:59 PM7/22/01
to
On Sun, 22 Jul 2001 18:08:09 -0400, "Tim Peters" <tim...@home.com>

wrote in comp.lang.python in article
<mailman.995839778...@python.org>:

:You don't have to defend yourself -- Guido will do it for you <wink>. He


:opened a bug report on SourceForge today:
:
: #443559 creating exceptions is underdocumented
:
:and attached one of your first msgs as evidence. This area is indeed
:"underdocumented".

Thanks. I needed that. <big grin>

Look, maybe after I've figured out exceptions, I can write up my own
understanding of them, and see how that flies?

phaw...@spamnotconnact.com

unread,
Jul 22, 2001, 11:07:32 PM7/22/01
to
Oh, fer crying out loud, Sheila just wants an example of exceptions in
use; she said so quite specifically and unambiguously. The hard part
about exceptions is that they're way simpler than you think.

Here you go, Sheila, a nice little camera interface, uses exceptions.
It uses an argument instead of defining __str__, which I hadn't realized
was a possibility. Hmmm, interesting (playing in Idle), defining
__str__ as you do causes an exception to not take an argument. See
next post...


import string
import commands
import exceptions
import re
import os.path
from glob import glob

class Camera:
"""A class abstracting the camera interface; designed to call a command-line interface tool"""

def __init__(self, camera = "/dev/kodak"):
if not os.path.exists(camera):
raise NoDevice, "device does not exist" + camera
else:
self.__camera = camera
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " settime")

def download_images(self):
if self.is_on():
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " download")
else:
raise NotResponding, "Camera not responding"

def download_thumbs(self):
if self.is_on():
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " thumbs")
else:
raise NotResponding, "Camera not responding"
self.convert_thumbnails()

def convert_thumbnails(self):
for thumb in glob('*.ppm'):
thumb_path, discard = os.path.splitext(thumb)
if not os.path.exists(thumb_path + 'thmb.jpg'):
commands.getoutput('convert ' + thumb + " " + thumb_path + 'thmb.jpg')

def is_on(self):
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " getpowermode")
if re.search("camera is on", result):
return 1
elif re.search("camera is off", result):
return 0
else:
raise IOError, "Bad output from camera check -- " + result

def delete_all_images(self):
if self.is_on():
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " delall")
else:
raise NotResponding, "Camera not responding"

def n_images(self):
if self.is_on():
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " status")
match = re.search("(\d+)", result)
return int(match.group(1))
else:
raise NotResponding, "Camera not responding"

def shoot(self):
# Todo: add a timestamp every time this is called; check and wait 30 seconds
# before shooting again so camera can finish processing.

if self.is_on():
result = commands.getoutput("/usr/local/bin/ks -d " + self.__camera + " shoot")
else:
raise NotResponding, "Camera not responding"

class CameraError(exceptions.Exception):
def __init__ (self, args = None):
self.args = args

class NoDevice(CameraError):
pass

class NotResponding(CameraError):
pass

--
Patricia J. Hawkins
Hawkins Internet Applications, LLC


phaw...@spamnotconnact.com

unread,
Jul 22, 2001, 11:27:28 PM7/22/01
to
Here's some exception behaviour I don't get. If I simply define an
exception class and use "pass" for the body, I can pass in arguments
when I raise it (see passException, below). If, like Sheila, I define
__str__, I can no longer pass in arguments -- even if I define __str__
with an argument -- see strException, and strExceptionWithArg.

Do I need to use variable args? No, that doesn't do the trick... see
varArgsStrException below.

>>> class strException(Exception):
def __str__(self):
return "string cheese?"


>>> raise strException
Traceback (innermost last):
File "<pyshell#4>", line 1, in ?
raise strException
strException: string cheese?
>>> class strExceptionWithArg(Exception):
def __str__(self,m):
return "string cheese? " + m


>>> raise strExceptionWithArg, "no thanks"
Traceback (innermost last):
File "<pyshell#7>", line 1, in ?
raise strExceptionWithArg, "no thanks"
strExceptionWithArg: <unprintable instance object>
>>> class passException(Exception):
pass

>>> raise passException
Traceback (innermost last):
File "<pyshell#11>", line 1, in ?
raise passException
passException:
>>> raise passException, "no thanks"
Traceback (innermost last):
File "<pyshell#12>", line 1, in ?
raise passException, "no thanks"
passException: no thanks

>>> class varArgsStrException(Exception):
def __str__(self, *args):
return "string cheese? " + str(args)

>>> raise varArgsStrException, "no thanks"
Traceback (innermost last):
File "<pyshell#18>", line 1, in ?
raise varArgsStrException, "no thanks"
varArgsStrException: string cheese? ()

Tim Peters

unread,
Jul 23, 2001, 12:00:30 AM7/23/01
to pytho...@python.org
[phaw...@spamnotconnact.com]
> ...
> import exceptions
> ...

> class CameraError(exceptions.Exception):
> def __init__ (self, args = None):
> self.args = args

Just noting that Exception is in the builtin namespace, so there's no need
to import the exceptions module first. That is, you can drop the import,
and change the declaration to

class CameraError(Exception):

i-was-surprised-too-when-barry-taught-me-that!-ly y'rs - tim


R. David Murray

unread,
Jul 23, 2001, 10:46:35 AM7/23/01
to
Erik Max Francis <m...@alcyone.com> writes:
>Sheila King wrote:
>> That's because the "big picture" is the general overview of how the
>> parent class works.
>The behavior of the parent class is as the library reference states: It
>implements __str__, __getitem__, __len__ (presumably), and args.
>Exception is just a class like everything else; other than having the
>behavior as specified in the reference, it's your typical class.

I agree with Sheila here: while I *can* subclass and develop based
solely on the the documentation, I have a much greater comfort level
when I can actually look at the *implementation* of the base class.
I realize that the goal of encapsulation is to make this unnecessary,
but I'm talking here as much about psychological comfort as anything
that affects my knowledge level. It probably does have an effect on
my productivity, though.

Still, I've been able to happily subclass from dictionary and list
(through UserDict and UserList) without caring how they are
implemented internally, so it's really just a personal nit and
not something anyone else should care about.

There is, however, a deeper sense in which pointing Shelia or myself
to the documentation in the Library Reference is *not* an adequate
answer to "this is what you need in order to subclass", and it not
merely a matter of providing some examples (though that certainly
helps a lot!). What the Library Reference lacks, at least with
regards to the built in types, is a single, comprehensive, and
concise list of *all* of the methods that a type implements, and
their semantics. In other words, the *complete* Interface of the
type; some way to answer the question: what is the expected behavior
of a class that is going to play the same role as this thing I am
subclassing? Right now I get that information (very effectively!)
out of files like exceptions.py and UserList.py. But we've lost
exceptions.py already, and we will soon lose UserList.py and its
friends.

I've looked at the Interfaces module (from Zope), and that could
form the basis of something that could auto-generate the answer to
this question. (It might not be enough by itself, though, because
I might still need documentation that would let me know which
combination of underlying Interfaces implemented by a class were
essential to the particular role that I am expecting my subclass
to fulfill.)

--RDM

Greg Ewing

unread,
Jul 23, 2001, 8:48:42 PM7/23/01
to
phaw...@spamnotconnact.com wrote:
>
> >>> raise strExceptionWithArg, "no thanks"

Shouldn't that be

raise strExceptionWithArg("no thanks")

?

According to my reading of the docs, the first form
is illegal, since if the exception is a class and a
value is supplied it is supposed to be a subclass of the
exception class.

The real mystery is why it seems to work in some
cases anyway...

--
Greg Ewing, Computer Science Dept, University of Canterbury,
Christchurch, New Zealand
To get my email address, please visit my web page:
http://www.cosc.canterbury.ac.nz/~greg

phaw...@spamnotconnact.com

unread,
Jul 24, 2001, 12:37:13 PM7/24/01
to
>>>>> "GE" == Greg Ewing <gr...@cosc.canterbury.ac.nz> writes:

GE> phaw...@spamnotconnact.com wrote:
>>
>> >>> raise strExceptionWithArg, "no thanks"

GE> Shouldn't that be

GE> raise strExceptionWithArg("no thanks")

GE> ?

GE> According to my reading of the docs, the first form
GE> is illegal, since if the exception is a class and a
GE> value is supplied it is supposed to be a subclass of the
GE> exception class.

Nope.

The applicable phrase in the doc, below, is: "otherwise, the argument
list consists of a single argument which is the second expression"

___
"raise_stmt: "raise" [expression ["," expression ["," expression]]]
If no expressions are present, raise re-raises the last
expression that was raised in the current scope.

Otherwise, raise evaluates its first expression, which must yield
a string, class, or instance object. If there is a second expression,
this is evaluated, else None is substituted. If the first
expression is a class object, then the second expression may be an
instance of that class or one of its derivatives, and then that
instance is raised. If the second expression is not such an instance,
the given class is instantiated. The argument list for the
instantiation is determined as follows: if the second expression is a
tuple, it is used as the argument list; if it is None, the
argument list is empty; otherwise, the argument list consists of a
single argument which is the second expression. If the first
expression is an instance object, the second expression must be
None."

http://www.python.org/doc/current/ref/raise.html#raise

0 new messages