Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I call an exception after I except it?

Why can't I raise an Exception instance after I catch that Exception class? Oddly enough, I run into this error when I run the script from a function but not when ran directly in the python shell.

In [2]: def do():
   ...:     try:
   ...:         raise ValueError('yofoo')
   ...:     except TypeError, ValueError:
   ...:         raise ValueError('yo')
   ...: 

In [3]: do()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-3-30c46b84d9a4> in <module>()
----> 1 do()

<ipython-input-2-b62158d6343b> in do()
      1 def do():
      2     try:
----> 3         raise ValueError('yofoo')
      4     except TypeError, ValueError:
      5         raise ValueError('yo')

UnboundLocalError: local variable 'ValueError' referenced before assignment

Expected error here:

In [3]: try:
   ...:     raise ValueError("foo")
   ...: except ValueError:
   ...:     raise ValueError("bar")
   ...: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-d5c83419a5ea> in <module>()
      2     raise ValueError("foo")
      3 except ValueError:
----> 4     raise ValueError("bar")
      5 

ValueError: bar
like image 645
Youcha Avatar asked Mar 11 '14 17:03

Youcha


1 Answers

except TypeError, ValueError:

should be

except (TypeError, ValueError):

When you use except TypeError, ValueError:, you are assigning the Exception instance to the variable name ValueError.

With your current code, when Python parses the do function, it notes ValueError is a local variable because except TypeError, ValueError: assigns a value to ValueError. But when you reference it in the first try-suite, with raise ValueError('yofoo'), the local variable ValueError has no value. So you get UnboundLocalError.


From the docs:

... except (RuntimeError, TypeError, NameError):
...     pass

Note that the parentheses around this tuple are required, because except ValueError, e: was the syntax used for what is normally written as except ValueError as e: in modern Python (described below). The old syntax is still supported for backwards compatibility. This means except RuntimeError, TypeError is not equivalent to except (RuntimeError, TypeError): but to except RuntimeError as TypeError: which is not what you want.

like image 177
unutbu Avatar answered Nov 20 '22 16:11

unutbu