Re: Simple way of handling errors

2009-05-07 Thread Matt Nordhoff
Steven D'Aprano wrote:
> On Wed, 06 May 2009 20:21:38 -0700, TomF wrote:
> 
>>> 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.
> 
> 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.
-- 
--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-07 Thread TomF

On 2009-05-07 01:01:57 -0700, Peter Otten <__pete...@web.de> said:


TomF wrote:


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


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


-Tom

--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-07 Thread Steven D'Aprano
On Wed, 06 May 2009 20:21:38 -0700, TomF wrote:

>> 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.

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.



-- 
Steven

--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-07 Thread Stephen Hansen
> If it fails, you get both a straight-forward error message and a useful
> traceback:
>
> Traceback (most recent call last):
>  File "", line 1, in 
> 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.
>

Unfortunately, I find that even halfway technically trained
(not necessarily naturally inclined or talented, but trained) users are
utterly unable to read tracebacks in real world situations. I had to put up
a rather big guide on how to read and interpret even the simplest ones
complete with color coding, "how to pick out a traceback visually", "what
line to focus your attention on (the last)", and "how trying to /read/ it
instead of immediately sending it to me as if it were an opaque symbol
containing secret knowledge only I can make sense of, generally saves you
time in debugging issues". I'm not talking about esoteric tracebacks either
resulting from real bugs and stuff. I'm talking about 'file not found'
'permission denied' IO/OS level ones that should give serious hints at
things people should check/diagnose themselves.

There's a serious, "oh my god, traceback, /eyes glazed over/" reaction all
around. Now these aren't unix people or command line people (except my
rote), but still.

I don't quite find printing out tracebacks to stdout or stderr ever
acceptable :( Especially if its an expected error condition (file not found
is a very good example of that).

I route all my tracebacks into log files for diagnosing later (people also
can not be relied upon to say anything but 'traceback' when they see one: so
storing it for later is vital. They read the first word and stop. The
thought of most-significant-information at the bottom is a difficult thing,
alas)

Anyways. ;-) That's just my experience.

As to the OP: try/except is how you do it in Python. There's no shorter or
easier way; exceptions are how Python handles failure-states (even
soft/expected errors quite often) and it does so pervasively (but not
universally).

--S
--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-07 Thread Peter Otten
TomF wrote:

> 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

--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-06 Thread TomF
On 2009-05-06 19:41:29 -0700, Steven D'Aprano 
 said:



On Wed, 06 May 2009 16:40:19 -0700, TomF wrote:


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.)


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 "", line 1, in 
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

--
http://mail.python.org/mailman/listinfo/python-list


Re: Simple way of handling errors

2009-05-06 Thread Steven D'Aprano
On Wed, 06 May 2009 16:40:19 -0700, TomF wrote:

> 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 "", line 1, in 
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))



-- 
Steven
--
http://mail.python.org/mailman/listinfo/python-list