[Tutor] general exception questions

Steven D'Aprano steve at pearwood.info
Tue Oct 6 03:29:24 CEST 2015


On Mon, Oct 05, 2015 at 01:46:52PM -0400, richard kappler wrote:
> I'm reading up on exception handling, and am a little confused. If you have
> an exception that just has 'pass' in it, for example in a 'for line in
> file:' iteration, what happens? Does the program just go to the next line?

Yes. The exception is caught and then processing continues in the usual 
manner from the except clause. In your example below, that would mean 
returning to the start of the for-loop.

> EX:
> 
> for line in file:
>     try:
>         do something
>     except:
>         pass
> 
> I know (so many of you have told me :-) that using pass is a bad idea

*scratches head*

I don't remember anyone saying that *pass* itself if a bad idea. On it's 
own, pass just tells the Python compiler to do nothing.

But what *really is* a bad idea is the bare "except" sitting there like 
a land mine, waiting to blow up in your face. Bare excepts have their 
uses, their *very rare* uses, but in general what they mostly do is hide 
bugs and make them much harder to fix.

https://realpython.com/blog/python/the-most-diabolical-python-antipattern/

What *may* be a bad idea is the "do something" inside a try clause -- 
it's hard to tell, without knowing what "do something" actually is.

try...except blocks are great, they are an extremely powerful and useful 
part of the Python programming language. But they are easy to misuse. 
Here are two simple rules for effectively and safely using try...except: 

(1) Put the *least amount of code possible* inside the try.

(2) Catch the *fewest number of exceptions* possible in the except.


If you remember those two rules, your try...except blocks will be much 
less likely to bite.

You should protect the least amount of code as you can inside the try. 
For example, this is probably a bad idea:


try:
    i = mylist.index("<tag>")
    del other[i + START]
    process(mylist)
except ValueError:
    # tag not found
    handle_missing_tag()


The *intention* is to catch the ValueError that is raised by index() 
when "<tag>" is not found, but in fact there are four different 
places where ValueError could, potentially, be raised:

- the call to index()
- the calculation of i + START
- the del start[...]
- the function call process(...)


Only in the first case is ValueError expected, and can be safely caught 
and handled. In the other three places, a ValueError would be totally
unexpected, and would indicate a bug that needs to be fixed. To fix the 
bug, you would need to see it in the first case, and you can't see it 
if it is caught and suppressed by the try...except.

This would probably be better written like this:

try:
    i = mylist.index("<tag>")
except ValueError:
    # tag not found
    handle_missing_tag()
else:
    del other[i + START]
    process(mylist)

or similar. Inside a function, you might do this:

def func():
    try:
        i = mylist.index("<tag>")
    except ValueError:
        # tag not found
        handle_missing_tag()
        return
    del other[i + START]
    process(mylist)


Now, if process() raises ValueError, you will see it, and can fix the 
bug.

Of course, there are times where being lazy is a virtue:

for x in sequence:
    try:
         process(x)
    except Exception:
         pass


is fine in the interactive interpreter, where you don't care about best 
practices, reliability, long-term maintainability, etc. You don't really 
care what goes wrong, you just want to keep going no matter what. But 
notice that I've caught Exception, rather than a bare except. I've done 
that so that I can interrupt the script and cancel processing with 
Ctrl-C, otherwise the KeyboardInterrupt exception will be caught and 
ignored too!

But even in this case, the quick-n-dirtiest of the quick-n-dirty 
scripts, there's a significant risk of failure:

for x in sequence:
    try:
         proces(x)  # Oops, typo.
    except Exception:
         pass


I have done this: intending to process a long list, I fired off the 
script, then came back an hour or two later only to discover that it had 
done *absolutely nothing* due to a silly typo.



-- 
Steve


More information about the Tutor mailing list