Alex
Alex

Reputation: 44305

pythonic way of raising an error within the try block

I have a method that checks something and which can

I want catch the exception properly to raise one myself, but also if the test returns False. The incorrect way to do this is

try:
    if not check():
        raise MyException()
except:
    raise MyException()

as the first MyException is caught after the except again. One way to handle this properly would be

try:
    flag = check()
except:
    raise MyException()
else:
    if not flag:
        raise MyException()

Is this the only way of dealing with this situation, or is there another way to handle it more efficient, getting rid of the flag variable?

Upvotes: 7

Views: 23416

Answers (3)

Sebastian Blask
Sebastian Blask

Reputation: 2938

You should never use except: because that catches ALL exceptions, including SystemExit, you should probably do:

try:
    if not check():
        raise MyNewException()
except ExceptionRaisedByCheck:
    raise MyNewException()

If the exception coming from check() is the same as the one you want to raise, you should change that.

Edit: If the exception is the same, you can also simply do this (Mark Byers had this in his answer, but it's gone now):

if not check():
    raise TheSameException()

This will propagate the exception or raise if False.

Upvotes: 12

Martijn Pieters
Martijn Pieters

Reputation: 1121584

In python 3.3, you can use the new contextlib.ExitStack context manager:

with ExitStack() as stack:
    stack.callback(lambda: raise MyException)

    if check():
        stack.pop_all()

This will raise MyException, unless you clear the stack callbacks with pop_all().

You can codify this is into a custom context manager:

from contextlib import ExitStack

class ExceptionUnlessCancelled(ExitStack):
    def __init__(self, exception, *args, **kw):
        super(Callback, self).__init__()
        self.exception = exception
        self.callback(self.raiseException, *args, **kwds)

    def raiseException(self, *args, **kw):
        raise self.exception(*args, **kw)

    def cancel(self):
        self.pop_all()

with ExceptionUnlessCancelled(MyException) as exc:
    if check():
        exc.cancel()

Upvotes: 1

jfs
jfs

Reputation: 414149

try:
   # whatever
except MyException:
   raise # reraise it
except Exception as e:
   raise MyException(some_info(e)) # unify user-visible exception type

Upvotes: 2

Related Questions