Simple way of handling errors

T

TomF

As a relative newcomer to Python, I like it a lot but I'm dismayed at
the difficulty of handling simple errors. In Perl if you want to
anticipate a file-not-found error you can simply do:

open($file) or die("open($file): $!");

and you get an intelligible error message. In Python, to get the same
thing it appears you need at least:

try:
f=open(file)
except IOError, err:
print "open(%s): got %s" % (file, err.strerror)
exit(-1)

Is there a simpler interface or idiom for handling such errors? I
appreciate that Python's exception handling is much more sophisticated
but often I don't need it.

-Tom
 
S

Steven D'Aprano

As a relative newcomer to Python, I like it a lot but I'm dismayed at
the difficulty of handling simple errors. In Perl if you want to
anticipate a file-not-found error you can simply do:

open($file) or die("open($file): $!");

and you get an intelligible error message. In Python, to get the same
thing it appears you need at least:

try:
f=open(file)
except IOError, err:
print "open(%s): got %s" % (file, err.strerror)
exit(-1)


Functions never fail silently in Python. (At least built-in functions
never fail silently. Functions you write yourself can do anything you
want.)


The canonical way of doing "open or die" in Python is to just call open:

f = open(filename)

If it fails, you get both a straight-forward error message and a useful
traceback:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'foomanchu'


The only reason you would bother going to the time and effort of catching
the error, printing your own error message, and then exiting, is if you
explicitly want to hide the traceback from the user.

Oh, and if you do that, I recommend that you print to stderr instead of
stdout:

print >>sys.stderr, "open(%s): got %s" % (file, err.strerror)

or

sys.stderr.write("open(%s): got %s\n" % (file, err.strerror))
 
T

TomF

Functions never fail silently in Python. (At least built-in functions
never fail silently. Functions you write yourself can do anything you
want.)

Well, yes, I'm aware that if you don't handle errors Python barfs out a
backtrace.
If it fails, you get both a straight-forward error message and a useful
traceback:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'foomanchu'

The only reason you would bother going to the time and effort of catching
the error, printing your own error message, and then exiting, is if you
explicitly want to hide the traceback from the user.

Well, to me, exposing the user to such raw backtraces is
unprofessional, which is why I try to catch user-caused errors. But I
suppose I have an answer to my question.

Thanks,
-Tom
 
S

Steven D'Aprano

Well, to me, exposing the user to such raw backtraces is unprofessional,
which is why I try to catch user-caused errors. But I suppose I have an
answer to my question.

That depends on your audience. Not every program is written to be used
for a technical incompetent audience. Some users actually *want* to see
the errors.

But certainly there are large classes of applications where you do want
to suppress the traceback. That's why I said "if you explicitly want to
hide the traceback from the user" rather than "don't do this".

The idiom I use is to wrap the *entire* application in a single
try...except block, and then put all your user-friendly error handling in
one place, instead of scattered over the entire application:


try:
main(sys.argv[1:])
except KeyboardInterrupt, SystemExit:
raise
except Exception, e:
log(e)
print >>sys.stderr, str(e)
sys.exit(1)



Hope this helps.
 
P

Peter Otten

TomF said:
As a relative newcomer to Python, I like it a lot but I'm dismayed at
the difficulty of handling simple errors. In Perl if you want to
anticipate a file-not-found error you can simply do:

open($file) or die("open($file): $!");

and you get an intelligible error message. In Python, to get the same
thing it appears you need at least:

try:
f=open(file)
except IOError, err:
print "open(%s): got %s" % (file, err.strerror)
exit(-1)

Is there a simpler interface or idiom for handling such errors? I
appreciate that Python's exception handling is much more sophisticated
but often I don't need it.

-Tom

While you are making the transition you could write

from perl_idioms import open_or_die

f = open_or_die("does-not-exist")


with the perl_idioms module looking like

import sys

def open_or_die(*args):
try:
return open(*args)
except IOError, e:
sys.exit(e)

Peter
 
T

TomF

While you are making the transition you could write

from perl_idioms import open_or_die

f = open_or_die("does-not-exist")


with the perl_idioms module looking like

import sys

def open_or_die(*args):
try:
return open(*args)
except IOError, e:
sys.exit(e)

Peter

Thanks. Rolling my own error module for common errors may be the best
way to go.

-Tom
 
M

Matt Nordhoff

Steven said:
Well, to me, exposing the user to such raw backtraces is unprofessional,
which is why I try to catch user-caused errors. But I suppose I have an
answer to my question.

That depends on your audience. Not every program is written to be used
for a technical incompetent audience. Some users actually *want* to see
the errors.

But certainly there are large classes of applications where you do want
to suppress the traceback. That's why I said "if you explicitly want to
hide the traceback from the user" rather than "don't do this".

The idiom I use is to wrap the *entire* application in a single
try...except block, and then put all your user-friendly error handling in
one place, instead of scattered over the entire application:


try:
main(sys.argv[1:])
except KeyboardInterrupt, SystemExit:

That should be:

except (KeyboardInterrupt, SystemExit):

;-D
raise
except Exception, e:
log(e)
print >>sys.stderr, str(e)
sys.exit(1)



Hope this helps.
--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top