FAQ
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

Search Discussions

  • Steven D'Aprano at May 7, 2009 at 2:41 am

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



    --
    Steven
  • Stephen Hansen at May 7, 2009 at 3:19 am

    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.
    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
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20090506/01b24428/attachment.htm>
  • TomF at May 7, 2009 at 3:21 am
    On 2009-05-06 19:41:29 -0700, Steven D'Aprano
    <steven at REMOVE.THIS.cybersource.com.au> 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 "<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
  • Steven D'Aprano at May 7, 2009 at 3:38 am

    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
  • Matt Nordhoff at May 7, 2009 at 4:24 pm

    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.
    --
  • Peter Otten at May 7, 2009 at 8:01 am

    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
  • TomF at May 7, 2009 at 3:39 pm

    On 2009-05-07 01:01:57 -0700, Peter Otten <__peter__ at 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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMay 6, '09 at 11:40p
activeMay 7, '09 at 4:24p
posts8
users5
websitepython.org

People

Translate

site design / logo © 2022 Grokbase