A little disappointed so far
Tom Bryan
tbryan at python.net
Tue May 20 08:31:43 EDT 2003
Graham Nicholls wrote:
>> But Alex will probably trundle by in a moment to tell you that in many
>> cases, you don't want to do that. Python's powerful exception handling
>> system means that most of the time you just do:
>>
>> try:
>> f = file(filename)
>> except IOError:
>> <handle exception>
>>
> I guess thats reasonably succinct.
>
>> Thing is, no matter how much you test, there's always the possibility of
>> a race condition that prevents you from opening a file. I'll note that
>> since you're mostly doing shell script equivalents, it's more likely
>> that you'll want to do the tests (because you want to know whether
>> something is a file or a directory).
>
> I suppose so, unless you've some sort of temporary file creation function.
> So, generally is it the "Python Way" to try things and handle the
> exceptions, as in try... except, or to run os.path.isfile ?
> Are there good reasons for this?
One thing it permits you to do is bubble up errors to the appropriate place.
In another reply, I mention that I ended up bundling up a bunch of code
into reusable functions and module in Python. While
open(FILE, $filename) || die "Couldn't open file $filename"
may be fine, succint, and charmingly readable in a flat script, you probably
don't want it buried down in four layers of functions calls. For example,
if I need a config file, I may write a little config file parser.
(Actually, I'd just use Python's ConfigParser module...proper impatience is
one of the three virtues in the Perl crowd, right?) Now, if I require the
config file to be present, the config file parser will attempt to open the
specified file and get an IOError. I certainly don't want the config file
parser to exit for me. That might be fine for the first program that used
it, but I may be able to recover from that error in another program.
Better to throw the exception up and deal with it at a higher level. (Of
course, now you're faced with the complication of deciding which errors you
need to handle at a higher level.)
This whole long-winded explanation is trying to say that
try:
f = file(filename)
# ...do 20 lines of work
except IOError:
<handle exception>
can be bundled up into a function in two ways
# move all of the code to a function
def foo(filename):
try:
f = file(filename)
# ...do 20 lines of work
except IOError:
<handle exception>
# later, in your main code, call the function
foo()
OR
# move just the work to a function
def foo(filename):
"""foo(ffilename) -> explanation of results
Throws an IOError if the filename is not a readable file."""
f = file(filename)
#...do 10 lines of work
# later, in your main code, call the function
try:
foo()
#...the remaining 10 lines of work
except IOError:
<handle exception>
So, one nice thing about exceptions is that you can bundle behavior for
later while leavnig some of the error handling at the top level. It's a
simple example, but I think that it makes the point. Like I said, this
choice adds some complexity in figuring out which exceptions to throw and
handle at which levels. But as you start to build up a bunch of modules
that you use in your code, you'd like the leave the code at the top level
in control of when to exit. It's much better than calling foo, which
calls bar, which calls baz, which instantiates a class and calls a method
that exits the entire program. :-)
---Tom
More information about the Python-list
mailing list