Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #5134 > unrolled thread

Proper way to handle errors in a module

Started byAndrew Berg <bahamutzero8825@gmail.com>
First post2011-05-11 12:29 -0500
Last post2011-05-13 10:56 +1000
Articles 12 — 8 participants

Back to article view | Back to comp.lang.python


Contents

  Proper way to handle errors in a module Andrew Berg <bahamutzero8825@gmail.com> - 2011-05-11 12:29 -0500
    Re: Proper way to handle errors in a module Roy Smith <roy@panix.com> - 2011-05-11 14:05 -0400
      Re: Proper way to handle errors in a module Andrew Berg <bahamutzero8825@gmail.com> - 2011-05-12 14:14 -0500
      Re: Proper way to handle errors in a module MRAB <python@mrabarnett.plus.com> - 2011-05-12 20:25 +0100
      Re: Proper way to handle errors in a module Andrew Berg <bahamutzero8825@gmail.com> - 2011-05-12 15:12 -0500
      Re: Proper way to handle errors in a module Corey Richardson <kb1pkl@aim.com> - 2011-05-12 16:20 -0400
      Re: Proper way to handle errors in a module Tycho Andersen <tycho@tycho.ws> - 2011-05-12 15:26 -0500
        Re: Proper way to handle errors in a module Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-13 00:43 +0000
      Re: Proper way to handle errors in a module MRAB <python@mrabarnett.plus.com> - 2011-05-12 21:26 +0100
      Re: Proper way to handle errors in a module Ethan Furman <ethan@stoneleaf.us> - 2011-05-12 13:40 -0700
      Re: Proper way to handle errors in a module Andrew Berg <bahamutzero8825@gmail.com> - 2011-05-12 15:35 -0500
        Re: Proper way to handle errors in a module Ben Finney <ben+python@benfinney.id.au> - 2011-05-13 10:56 +1000

#5134 — Proper way to handle errors in a module

FromAndrew Berg <bahamutzero8825@gmail.com>
Date2011-05-11 12:29 -0500
SubjectProper way to handle errors in a module
Message-ID<mailman.1415.1305134998.9059.python-list@python.org>
I'm a bit new to programming outside of shell scripts (and I'm no expert
there), so I was wondering what is considered the best way to handle
errors when writing a module. Do I just let exceptions go and raise
custom exceptions for errors that don't trigger a standard one? Have the
function/method return nothing or a default value and show an error
message? I'm sure there's not a clear-cut answer, but I was just
wondering what most developers would expect a module to do in certain
situations.

[toc] | [next] | [standalone]


#5139

FromRoy Smith <roy@panix.com>
Date2011-05-11 14:05 -0400
Message-ID<roy-FB35E1.14050911052011@news.panix.com>
In reply to#5134
In article <mailman.1415.1305134998.9059.python-list@python.org>,
 Andrew Berg <bahamutzero8825@gmail.com> wrote:

> I'm a bit new to programming outside of shell scripts (and I'm no expert
> there), so I was wondering what is considered the best way to handle
> errors when writing a module. Do I just let exceptions go and raise
> custom exceptions for errors that don't trigger a standard one? Have the
> function/method return nothing or a default value and show an error
> message? I'm sure there's not a clear-cut answer, but I was just
> wondering what most developers would expect a module to do in certain
> situations.

In general, raise an exception when there is no valid value that can be 
returned from a function.  Sometimes it makes more sense to return 0, 
None, an empty list, etc.  So:

count_vowels("banana") ==> 3
count_vowels("xyzzy") ==> 0  # counting "y" as not a vowel
count_vowels("") ==> 0
count_vowels(None) ==> raises TypeError

You want to raise specific errors.  Let's say you've got a function like 
this:

def airspeed(swallow):
   speeds = {"european": 42,
             "african", 196}
   return speeds[swallow]

If somebody passes an invalid string, it will raise KeyError as written.  
Better to do something like:

def airspeed(swallow):
   speeds = {"european": 42,
             "african", 196}
   try:
       return speeds[swallow]
   except KeyError:
        raise UnknownBirdError(swallow)

This lets somebody catch UnknownBirdError at some higher level and do 
something useful.  If you let KeyError escape, that's a lot harder to 
deal with because it could come from almost anywhere.

[toc] | [prev] | [next] | [standalone]


#5250

FromAndrew Berg <bahamutzero8825@gmail.com>
Date2011-05-12 14:14 -0500
Message-ID<mailman.1482.1305227667.9059.python-list@python.org>
In reply to#5139
On 2011.05.11 01:05 PM, Roy Smith wrote:
> You want to raise specific errors.  Let's say you've got a function like 
> this:
>
> def airspeed(swallow):
>    speeds = {"european": 42,
>              "african", 196}
>    return speeds[swallow]
>
> If somebody passes an invalid string, it will raise KeyError as written.  
> Better to do something like:
>
> def airspeed(swallow):
>    speeds = {"european": 42,
>              "african", 196}
>    try:
>        return speeds[swallow]
>    except KeyError:
>         raise UnknownBirdError(swallow)
Is there any way to do this without purposely setting up the code to
trigger an arbitrary exception if the function can't do its job? That
is, can I raise an UnknownBirdError outside of an except clause, and if
so, how? I can't find much help for doing this in Python 3, even in the
official docs.

[toc] | [prev] | [next] | [standalone]


#5251

FromMRAB <python@mrabarnett.plus.com>
Date2011-05-12 20:25 +0100
Message-ID<mailman.1485.1305228330.9059.python-list@python.org>
In reply to#5139
On 12/05/2011 20:14, Andrew Berg wrote:
> On 2011.05.11 01:05 PM, Roy Smith wrote:
>> You want to raise specific errors.  Let's say you've got a function like
>> this:
>>
>> def airspeed(swallow):
>>     speeds = {"european": 42,
>>               "african", 196}
>>     return speeds[swallow]
>>
>> If somebody passes an invalid string, it will raise KeyError as written.
>> Better to do something like:
>>
>> def airspeed(swallow):
>>     speeds = {"european": 42,
>>               "african", 196}
>>     try:
>>         return speeds[swallow]
>>     except KeyError:
>>          raise UnknownBirdError(swallow)
> Is there any way to do this without purposely setting up the code to
> trigger an arbitrary exception if the function can't do its job? That
> is, can I raise an UnknownBirdError outside of an except clause, and if
> so, how? I can't find much help for doing this in Python 3, even in the
> official docs.
 >
You can raise an exception wherever you like! :-)

[toc] | [prev] | [next] | [standalone]


#5255

FromAndrew Berg <bahamutzero8825@gmail.com>
Date2011-05-12 15:12 -0500
Message-ID<mailman.1490.1305231165.9059.python-list@python.org>
In reply to#5139
On 2011.05.12 02:25 PM, MRAB wrote:
> You can raise an exception wherever you like! :-)
If I raise an exception that isn't a built-in exception, I get something
like "NameError: name 'HelloError' is not defined". I don't know how to
define the exception.

[toc] | [prev] | [next] | [standalone]


#5257

FromCorey Richardson <kb1pkl@aim.com>
Date2011-05-12 16:20 -0400
Message-ID<mailman.1491.1305231953.9059.python-list@python.org>
In reply to#5139
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 05/12/2011 04:12 PM, Andrew Berg wrote:
> On 2011.05.12 02:25 PM, MRAB wrote:
>> You can raise an exception wherever you like! :-)
> If I raise an exception that isn't a built-in exception, I get something
> like "NameError: name 'HelloError' is not defined". I don't know how to
> define the exception.

class HelloError(Exception):
    pass

Of course, there are all sorts of other things you could do with your
exception.

http://docs.python.org/tutorial/errors.html#user-defined-exceptions
- -- 
Corey Richardson
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNzED9AAoJEAFAbo/KNFvp1uQIAKFaKyD1Q3RL7LGFSmnyRFTK
9XWRH3CSM9mOALccfQ8bUkrquol1fAqhrm4jyOW0scWmsJpRlcb6Rj4HtrmMQOuG
DpsUzEZCTnT9Xk80OeTFbpWWBIVBkxdhCxCl75XAP22o5EjhHpgLyqoqMD+81BKH
5/JWAGRJx/9E4BvNWsxIUhb1jlz+XT4H1XykTE1UUOP0uZneWRJMs7P12WNiL2Ii
HT0hEUhQc1eP1fJ5BqPB/6/B9q/KxTbN55hCq1VwwfRhgbaM4kR7Bekri7QUHGAK
1MKxRa1v+Co59y+ywAIH92L3wky3xNyFrUlFzK4AwYOnwRkVvUWw7vPG1iShE+k=
=2+y6
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#5258

FromTycho Andersen <tycho@tycho.ws>
Date2011-05-12 15:26 -0500
Message-ID<mailman.1492.1305231999.9059.python-list@python.org>
In reply to#5139
On Thu, May 12, 2011 at 03:12:39PM -0500, Andrew Berg wrote:
> On 2011.05.12 02:25 PM, MRAB wrote:
> > You can raise an exception wherever you like! :-)
> If I raise an exception that isn't a built-in exception, I get something
> like "NameError: name 'HelloError' is not defined". I don't know how to
> define the exception.

You'll have to define it, as you would anything else (exceptions are
just regular "things"; in fact you can raise anything that's a class
or instance). I typically don't put a whole lot in my exception
classes, though.

point:~/working$ python
Python 2.6.2 (r262:71600, Jun  8 2009, 11:11:42) 
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class HelloError(Exception): pass
... 
>>> raise HelloError("hello!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  __main__.HelloError: hello!

\t

[toc] | [prev] | [next] | [standalone]


#5274

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-05-13 00:43 +0000
Message-ID<4dcc7e9a$0$29980$c3e8da3$5496439d@news.astraweb.com>
In reply to#5258
On Thu, 12 May 2011 15:26:27 -0500, Tycho Andersen wrote:

> On Thu, May 12, 2011 at 03:12:39PM -0500, Andrew Berg wrote:
>> On 2011.05.12 02:25 PM, MRAB wrote:
>> > You can raise an exception wherever you like! :-)
>> If I raise an exception that isn't a built-in exception, I get
>> something like "NameError: name 'HelloError' is not defined". I don't
>> know how to define the exception.
> 
> You'll have to define it, as you would anything else (exceptions are
> just regular "things"; in fact you can raise anything that's a class or
> instance).

Not quite.

>>> raise 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: exceptions must be classes or instances, not int

Not a very good error message, because 42 is an instance!

>>> isinstance(42, int)
True

In Python 3, you get a better error message, and further restrictions on 
what you can raise:

>>> raise 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: exceptions must derive from BaseException


In general, you should always subclass Exception rather than 
BaseException. There are, er, exceptions, but for error-handling you 
normally should inherit from Exception directly, or some sub-class like 
ValueError, KeyError, etc.




-- 
Steven

[toc] | [prev] | [next] | [standalone]


#5259

FromMRAB <python@mrabarnett.plus.com>
Date2011-05-12 21:26 +0100
Message-ID<mailman.1493.1305232018.9059.python-list@python.org>
In reply to#5139
On 12/05/2011 21:12, Andrew Berg wrote:
> On 2011.05.12 02:25 PM, MRAB wrote:
>> You can raise an exception wherever you like! :-)
> If I raise an exception that isn't a built-in exception, I get something
> like "NameError: name 'HelloError' is not defined". I don't know how to
> define the exception.

Define it as a subclass of Exception:

     class UnknownBirdError(Exception):
         pass

[toc] | [prev] | [next] | [standalone]


#5260

FromEthan Furman <ethan@stoneleaf.us>
Date2011-05-12 13:40 -0700
Message-ID<mailman.1494.1305232074.9059.python-list@python.org>
In reply to#5139
Andrew Berg wrote:
> On 2011.05.12 02:25 PM, MRAB wrote:
>> You can raise an exception wherever you like! :-)
> If I raise an exception that isn't a built-in exception, I get something
> like "NameError: name 'HelloError' is not defined". I don't know how to
> define the exception.

class HelloError(Exception):
     "custom exception"

and that's all you need.  You can override __init__ to add your own 
attributes, etc, if you need to.

~Ethan~

[toc] | [prev] | [next] | [standalone]


#5261

FromAndrew Berg <bahamutzero8825@gmail.com>
Date2011-05-12 15:35 -0500
Message-ID<mailman.1495.1305232521.9059.python-list@python.org>
In reply to#5139
On 2011.05.12 03:20 PM, Corey Richardson wrote:
> class HelloError(Exception):
>     pass
>
> Of course, there are all sorts of other things you could do with your
> exception.
>
> http://docs.python.org/tutorial/errors.html#user-defined-exceptions
So that's where that info is. I wasn't looking in the tutorial section.
Thanks!

[toc] | [prev] | [next] | [standalone]


#5276

FromBen Finney <ben+python@benfinney.id.au>
Date2011-05-13 10:56 +1000
Message-ID<87r583ifkh.fsf@benfinney.id.au>
In reply to#5261
Andrew Berg <bahamutzero8825@gmail.com> writes:

> So that's where that info is. I wasn't looking in the tutorial
> section.

Does this mean you haven't worked through the tutorial? Time to remedy
that.

-- 
 \     “You are welcome to visit the cemetery where famous Russian and |
  `\    Soviet composers, artists, and writers are buried daily except |
_o__)                   Thursday.” —Russian orthodox monastery, Moscow |
Ben Finney

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web