7

I have a method that checks something and which can

  • raise an exception itself
  • return True
  • return False

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?

4
  • 5
    First of all: don't use blanket except: catching, always only catch specific exceptions. Commented Oct 4, 2012 at 9:23
  • @avasal: what makes you think the OP doesn't know about raise? Commented Oct 4, 2012 at 9:23
  • You should add what Exception is raised in check(), because as you can see from the answers: there are a few ways to do this. Commented Oct 4, 2012 at 9:48
  • yes, always except for a specific exception in the normal case. But when you run something on a server, you don't want the server stop because of an error, you want to propagate ANY error to the client. Commented Oct 4, 2012 at 11:52

3 Answers 3

12

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.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 this doesn't strictly answer the question, but IMHO the question is just not really thought out very well. This is almost certainly better than whatever the OP mistakenly assumed was a good idea, though without some more background it's hard to tell what he's trying to do.
@MarkByers you deleted your answer? I edited mine to add part of your answer because that was really the simplest solution and I didn't think about it before. As you said, hard to tell what the objective is.
2
try:
   # whatever
except MyException:
   raise # reraise it
except Exception as e:
   raise MyException(some_info(e)) # unify user-visible exception type

Comments

1

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

2 Comments

Seems a little over-engineered, but still, interesting solution!
@SebastianBlask: I think context managers are great ways of dealing with complex exception situations. The OP's situation has been simplified for the question, who knows how much more code surrounds the check?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.