I often find myself wanting to do something like this, I have something wrapped in try excepts like this
item= get_item()
try:
do_work(item)
except SomeError as err:
if err.code == 123:
do_something(item)
else:
# Actually I don't want to do something with this error code... I want to handle in 'except'
except:
put_back(item)
raise
Is there a way to raise into the except
block below from the else? (a continue
would be nice) I end up doing something like the following which isn't as clean
item= get_item()
try:
try:
do_work(item)
except SomeError as err:
if err.code == 123:
do_something(item)
else:
raise
except:
put_back(item)
raise
Is there anyway to do that?
If you are using a recent enough python version (2.5 and up), you should switch to using a context manager instead:
class WorkItemContextManager(object):
def __enter__(self):
self.item = get_item()
return self.item
def __exit__(self, exc_type, exc_value, tb):
if exc_type is not None:
if exc_type is SomeError and exc_value.code == 123:
do_something(self.item)
return True # Exception handled
put_back(self.item)
Then:
with WorkItemContextManager() as item:
do_work(item)
The __exit__
method can return True if an exception has been handled; returning None will instead re-raise any exceptions raised in the with
block.
If not, you are looking for a finally
block instead:
item = get_item()
try:
do_work(item)
item = None
except SomeError as err:
if err.code == 123:
do_something(item)
item = None
finally:
if item is not None:
put_back(item)
The finally
suite is guaranteed to be executed when the try:
suite completes, or an exception has occurred. By setting item
to None
you basically tell the finally
suite everything completed just fine, no need to put it back.
The finally
handler takes over from your blanket except
handler. If there has been an exception in do_work
, item
will not be set to None. If the SomeError
handler doesn't catch the exception, or err.code
is not 123, item
will also not be set to None, and thus the put_back(item)
method is executed.
My suggestion would be to create a function (or series of functions) that wraps the method throwing errors which you'd like to control. Something like...
def wrapper(arg):
try:
do_work(arg)
except SomeError as e:
if e.code == 123:
do_something(item)
# Other possible cleanup code
else:
raise
...then, when you want to call it...
try:
wrapper(arg)
except SomeError as e:
put_back(arg)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With