Python Forum

Full Version: can i raise an exception in a try clause?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
there are these two kinds of exceptions: those that "happen" and those that are explicitly raised. the latter probably covers most everything because implementations have to decide the case for exceptions.

there are these two kinds of exceptions: those that are explicitly raised in a try clause and those that happen somewhere else as a result of what is being done in a try clause. the compiler, perhaps when optimizing, could shortcut the explicit raise because it sees a match between the exception being raised and that exception being one that is handled right there.

try:
    if foo:
        raise bar()
    duh(1)
except bar:
    duh(2)
that would be a long way to decide how to call duh(). maybe the compiler might try to optimize it and do:
duh(1 if foo else 2)
would that change have an impact? i don't really know. that's why i'm asking.
Skaperen Wrote:would that change have an impact?
Every change has an impact in python because of its infinite reflection capabilities. Suppose duh() is
def duh(n):
    if n == 2 and sys.exc_info()[0] is None:
        shutil.rmtree(HOMEDIR)
then your optimized version will destroy the home directory and its contents.
i'm thinking of side effects of optimization that could be considered acceptable if a language rule does not allow an explicit raise in a try. i have not seen any such rule but me not seeing something does not mean it does not exist.
From the documentation
Quote:If no expressions are present, raise re-raises the last exception that was active in the current scope. If no exception is active in the current scope, a RuntimeError exception is raised indicating that this is an error.

Otherwise, raise evaluates the first expression as the exception object. It must be either a subclass or an instance of BaseException. If it is a class, the exception instance will be obtained when needed by instantiating the class with no arguments.
The only way a raise is different is if you don't provide an expression following it or if that expression is not a form of BaseException. If there is no difference then the compiler will handle it the same way.

So there is a tiny difference, but only if you do not provide an expression. The optimum use of this is to (re)raise within an except, rather than a try. This allows an exception that cannot be, or should not be handled locally to be handled by an except that is further up the stack.
try:
    will_have_exception()
except SpecificException as e:
    if not able_to_be_handled(e):
        raise
    handle_it_here(e)
However, I know of no evidence that a raise is optimized inside or outside of a try statement. If fact I do believe that the use of raise with any expression in the form of BaseExpression cannot be optimized into non exception code as it is necessarily capable of emptying/interrupting the stack.

The opcode for raise is RAISE_VARARGS(argc)
Quote:RAISE_VARARGS(argc)ΒΆ
Raises an exception using one of the 3 forms of the raise statement, depending on the value of argc:
0: raise (re-raise previous exception)
1: raise TOS (raise exception instance or type at TOS)
2: raise TOS1 from TOS (raise exception instance or type at TOS1 with __cause__ set to TOS)

I don't think I'm wrong but I'm open to any additional or contrary information that anyone has.

I'm curious to know why this is so important, please?
you probably are right. the optimization i was thinking about was compiler (in higher optimization mode) detecting a raise that is handled in an except that follows and optimizing a shortcut to that handler code as a shortcut for speedup. i hope you are absolutely right.
Pages: 1 2