By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,768 Members | 2,004 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,768 IT Pros & Developers. It's quick & easy.

Best practise hierarchy for user-defined exceptions

P: n/a
Hi there,

I am a newcomer to Pyhton coming from Java working on a relatively
large Pyhton project with several packages and modules. To improve
exception handling I would like to introduce some user-defined
exceptions to distinguish between exceptions raised in self-written
code as compared to std libray modules used there-in.

Say, for instance I would like to define a MyParseError exception to
indicate that something has gone wrong while parsing a byte string, a
file, or while packing into or unpacking from a struct.Struct
instance.

Here is my stub-implemented idea on how to do it so far, which is
inspired by how I would have done it in Java (but which may not be
very Pythonic??):

class MyException(Exception):

pass

class MyStandardError(MyException, StandardError):

pass

class MyParseError(MyStandardError, ValueError):

pass

Some comments and questions

1. The hierarchy is deliberately deep and maps to the std library such
that it is easier to extend
2. The implementations are empty but can be extended with hook for
logging, statistics, etc.
3. I use multiple inheritance in the two sub-classes. I have not tried
that before. Is this A Good Thing or A Bad Thing to do?
4. Which __xx__ methods would you normally implement for the user-
defined exception classes? I was thinking of __str__, for example? Is
there a recommended __str__ idiom to use for that?

-- Slaunger
Nov 17 '08 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On Mon, Nov 17, 2008 at 3:47 AM, Slaunger <Sl******@gmail.comwrote:
Hi there,

I am a newcomer to Pyhton coming from Java working on a relatively
large Pyhton project with several packages and modules. To improve
exception handling I would like to introduce some user-defined
exceptions to distinguish between exceptions raised in self-written
code as compared to std libray modules used there-in.

Say, for instance I would like to define a MyParseError exception to
indicate that something has gone wrong while parsing a byte string, a
file, or while packing into or unpacking from a struct.Struct
instance.

Here is my stub-implemented idea on how to do it so far, which is
inspired by how I would have done it in Java (but which may not be
very Pythonic??):

class MyException(Exception):

pass
The above class probably isn't necessary. You don't need to
overgeneralize this much.
class MyStandardError(MyException, StandardError):

pass
Rename the previous class to just MyError in light of removing the other class.
>
class MyParseError(MyStandardError, ValueError):

pass
This technique is very Pythonic. Subclass from both the exception
class for your module and from a built-in one if there's an applicable
one.
>
Some comments and questions

1. The hierarchy is deliberately deep and maps to the std library such
that it is easier to extend
Zen of Python: Flat is better than nested.
This is part of the reason I recommend removing the one class.
2. The implementations are empty but can be extended with hook for
logging, statistics, etc.
True of stubs in general...
3. I use multiple inheritance in the two sub-classes. I have not tried
that before. Is this A Good Thing or A Bad Thing to do?
Good in this case, just be careful to use super() if you override any methods.
4. Which __xx__ methods would you normally implement for the user-
defined exception classes? I was thinking of __str__, for example? Is
there a recommended __str__ idiom to use for that?
You might override __init__ if you want to store additional
information about the cause of the exception (e.g. location of parse
error, name of the rule the error occurred in, etc).
The __str__ inherited from Exception is usually sufficient, but you
can override it if you want to. it's a judgement call IMHO.

Cheers,
Chris
--
Follow the path of the Iguana...
http://rebertia.com
>
-- Slaunger
--
http://mail.python.org/mailman/listinfo/python-list
Nov 17 '08 #2

P: n/a
On 17 Nov., 13:05, "Chris Rebert" <c...@rebertia.comwrote:
On Mon, Nov 17, 2008 at 3:47 AM, Slaunger <Slaun...@gmail.comwrote:
.....
Here is my stub-implemented idea on how to do it so far, which is
inspired by how I would have done it in Java (but which may not be
very Pythonic??):
class MyException(Exception):
* *pass

The above class probably isn't necessary. You don't need to
overgeneralize this much.
Seems reasonable.
class MyStandardError(MyException, StandardError):
* *pass

Rename the previous class to just MyError in light of removing the other class.

OK.
>
class MyParseError(MyStandardError, ValueError):
* pass

This technique is very Pythonic. Subclass from both the exception
class for your module and from a built-in one if there's an applicable
one.

OK. One thing I *like* about it is that I inherit properties of
ValueError.

One thing I feel *a little uneasy about* is that if I do something
like this

try:
do_something_which_raises_MyParseError_which_I_hav e_overlooked()
do_something_where_I_know_a_ValueError_can_be_rais ed()
catch ValueError:
handle_the_anticipated_ValueError_from_std_lib()
finally:
....

I will not notice that it was an unanticpated condition in my own
code, which caused the ValueError
to be raised. If I had just inherited from MyError, it would fall
through (which I would prefer)

Once I had seen a trace back to the unanticipated MyParseError I would
of course correct the code to

try:
do_something_where_I_now_know_MyParseError_can_be_ raised()
do_something_where_I_know_a_ValueError_can_be_rais ed()
catch MyParseError:
handle_the_anticipated_MyParseError_generated_in_o wn_code()
catch ValueError:
handle_the_anticipated_ValueError_from_std_lib()
finally:
....

Is the above multiple catch methology pythonic as well?

On the other hand, with multiple inheritance this works:

try:
do_something_where_I_know_a_MyParseError_can_be_ra ised()
do_something_where_I_know_a_ValueError_can_be_rais ed()
catch ValueError:
handle_a_MyParseError_or_a_ValueError_in_the_same_ manner()
finally:
....

which is nice is you are very aware that MyParseError descends from
ValueError (which may not be self-evident)

>
Some comments and questions
1. The hierarchy is deliberately deep and maps to the std library such
that it is easier to extend

Zen of Python: Flat is better than nested.
This is part of the reason I recommend removing the one class.
Ah, OK, have to adjust my mindset a little. Willing to accomodate
though... ;-)
>
3. I use multiple inheritance in the two sub-classes. I have not tried
that before. Is this A Good Thing or A Bad Thing to do?

Good in this case, just be careful to use super() if you override any methods.
I will!
>
4. Which __xx__ methods would you normally implement for the user-
defined exception classes? I was thinking of __str__, for example? Is
there a recommended __str__ idiom to use for that?

You might override __init__ if you want to store additional
information about the cause of the exception (e.g. location of parse
error, name of the rule the error occurred in, etc).
The __str__ inherited from Exception is usually sufficient, but you
can override it if you want to. it's a judgement call IMHO.
OK. Seems pretty straight-forward. I like Python more and more.
Cheers,
Chris
That was a very useful answer. Thank you, Chris for taking your time
to reply on my questions.

Cheers,
-- Slaunger
Nov 17 '08 #3

P: n/a
Slaunger <Sl******@gmail.comwrote:
On 17 Nov., 13:05, "Chris Rebert" <c...@rebertia.comwrote:
On Mon, Nov 17, 2008 at 3:47 AM, Slaunger <Slaun...@gmail.comwrote:
.....
Here is my stub-implemented idea on how to do it so far, which is
inspired by how I would have done it in Java (but which may not be
very Pythonic??):
class MyException(Exception):
? ?pass
The above class probably isn't necessary. You don't need to
overgeneralize this much.
Seems reasonable.
class MyStandardError(MyException, StandardError):
? ?pass
Rename the previous class to just MyError in light of removing the other class.
OK.
class MyParseError(MyStandardError, ValueError):
? pass
This technique is very Pythonic. Subclass from both the exception
class for your module and from a built-in one if there's an applicable
one.
OK. One thing I *like* about it is that I inherit properties of
ValueError.

One thing I feel *a little uneasy about* is that if I do something
like this

try:
do_something_which_raises_MyParseError_which_I_hav e_overlooked()
do_something_where_I_know_a_ValueError_can_be_rais ed()
catch ValueError:
handle_the_anticipated_ValueError_from_std_lib()
finally:
....

I will not notice that it was an unanticpated condition in my own
code, which caused the ValueError
to be raised. If I had just inherited from MyError, it would fall
through (which I would prefer)
I'd say if the above code worries you, then MyParseError isn't a
ValueError and you shouldn't inherit from ValueError.

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Nov 17 '08 #4

P: n/a
Nick Craig-Wood wrote:
Slaunger <Sl******@gmail.comwrote:
>.... I will not notice that it was an unanticpated condition
in my own code, which caused the ValueError to be raised.
If I had just inherited from MyError, it would fall through....

I'd say if the above code worries you, then MyParseError isn't a
ValueError and you shouldn't inherit from ValueError.
Just from the name, I'd look into making MyParseError inherit from
SyntaxError.

--Scott David Daniels
Sc***********@Acm.Org
Nov 19 '08 #5

This discussion thread is closed

Replies have been disabled for this discussion.