Modern recommended exception handling practices?
Chris Angelico
rosuav at gmail.com
Tue Nov 3 02:52:27 EST 2015
On Tue, Nov 3, 2015 at 6:22 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> A lot can happen in the few microseconds between
> checking for the existence of the file and actually opening it -- the file
> could be renamed or deleted.
And a lot of microseconds can happen between two opcodes, too. Even
inside a Python script, it's possible for threads or other arbitrary
code execution to get in your way:
if "foo" in counters:
# context switch here!
process(counters["foo"])
Garbage collection can happen at any time. Here's an (admittedly
arbitrary) example of how the above could be broken:
>>> class X:
... def __init__(self, name, dict):
... self.dict = dict; self.name = name
... self.dict[self.name] = 0
... def frob(self):
... self.dict[self.name] += 1
... def __del__(self):
... del self.dict[self.name]
...
>>> counters = {}
>>> x = X("foo", counters)
>>> x.refcycle = x
>>> counters
{'foo': 0}
>>> del x
>>> counters
{'foo': 0}
>>> gc.collect()
10
>>> counters
{}
If the cycle-detecting garbage collector happens to be called
immediately after the 'if', you'll get an exception.
So I suppose what you might do is this:
try:
# Optimization: Since a lot of these names won't be
# in the dict, we check first rather than relying on the
# exception. Since counters get removed in the __del__
# method, we can't depend 100% on the 'in' check,
# but an unnecessary try block is cheap.
if "foo" in counters:
process(counters["foo"])
except KeyError:
pass
But any time you need a block comment to justify your code, you'd
better be REALLY sure the performance benefit is worth the complexity.
For reliability, expect exceptions.
ChrisA
More information about the Python-list
mailing list