exception handling in complex Python programs

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Aug 20 13:59:34 EDT 2008


On Wed, 20 Aug 2008 09:23:22 -0700, dbpokorny at gmail.com wrote:

> On Aug 19, 4:12 pm, Steven D'Aprano <st... at REMOVE-THIS-
> cybersource.com.au> wrote:
>> On Tue, 19 Aug 2008 11:07:39 -0700, dbpoko... at gmail.com wrote:
>> >   def do_something(filename):
>> >     if not os.access(filename,os.R_OK):
>> >       return err(...)
>> >     f = open(filename)
>> >     ...
>>
>> You're running on a multitasking modern machine, right? What happens
>> when some other process deletes filename, or changes its permissions,
>> in the time after you check for access but before you actually open it?
> 
> This is a good point - if you want to use the correct way of opening
> files, and
> you don't want to worry about tracking down exception types, then we can
> probably
> agree that the following is the simplest, easiest-to-remember way:
> 
>   def do_something(filename):
>     try:
>       f = open(filename)
>     except:
>       <handle exception>

No, we don't agree that that is the correct way of opening files. Simple 
it might be, but correct it is not.

If you're using Python 2.6 or greater, then you should be using a with 
block to handle file opening.

And regardless of which version of Python, you shouldn't use a bare 
except. It will mask exceptions you *don't* want to catch, including 
programming errors, typos and keyboard interrupts.



> Opening files is a special case where EAFP is the only correct solution
> (AFAIK). I still liberally sprinkle LBYL-style "assert isinstance(...)"

Oh goodie. Another programmer who goes out of his way to make it hard for 
other programmers, by destroying duck-typing.

BTW, assertions aren't meant for checking data, because assertions can be 
turned off. Outside of test frameworks (e.g. unit tests), assertions are 
meant for verifying program logic:

def foo(x):
    # This is bad, because it can be turned off at runtime,
    # destroying your argument checking.
    assert isinstance(x, int)
    # And it raises the wrong sort of exception.

    # This is better (but not as good as duck-typing).
    if not isinstance(x, int):
        raise TypeError('x not an int')
        # And it raises the right sort of error.

    y = some_function(x)
    # y should now be between -1 and 1.
    assert -1 < y < 1
    do_something_with(y)




> and other similar assertions in routines. The point is that EAFP
> conflicts with the interest of reporting errors as soon as possible

Not necessarily. Tell me how this conflicts with reporting errors as soon 
as possible:

def do_something(filename):
    try:
        f = open(filename)
    except IOError, e:
        report_exception(e)  # use a GUI, log to a file, whatever...

How could you report the exception any earlier than immediately? 




-- 
Steven



More information about the Python-list mailing list