简体   繁体   中英

Use exception variable in finally block

When running this example func:

from typing import Tuple, Any, Optional

def func() -> Tuple[Any, Optional[Exception]]:
    exc = None
    ret = None
    try:
        # code here, if successful assign result to `ret`
        ret = "Result"
        # comment this line out and the code works
        raise Exception
    except Exception as exc:
        exc.__traceback__ = None
        # Error logging here
        pass
    finally:
        return ret, exc

print(func())  # expected: ("Result", <Exception instance>)

the last line ( return ret, exc ) raises UnboundLocalError: local variable 'exc' referenced before assignment even tho exc is definitively bound in the first line of the function ( exc = None ). This can be fixed by changing the except -clause like so:

except Exception as exc1:
    exc = exc1
    exc.__traceback__ = None
    # Error logging here
    pass

Questions :

  1. Is it possible to avoid using another variable (in my example exc1 ) while still avoiding the UnboundLocalError ?
  2. Why does the except <Exception> as <var> statement "swallow" already defined local variables?

This case is described in 8.4. The try statement :

When an exception has been assigned using as target, it is cleared at the end of the except clause. This is as if

except E as N: foo

was translated to

 try: foo finally: del N

This means the exception must be assigned to a different name to be able to refer to it after the except clause . Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM