What does raise
do, if it's not inside a try
or except
clause, but simply as the last statement in the function?
def foo(self):
try:
# some code that raises an exception
except Exception as e:
pass
# notice that the "raise" is outside
raise
This example prints 1 but not 2 so it must be that the last raise
statement simply raises the last thrown exception.
def foo():
try:
raise Exception()
except Exception as e:
pass
print 1
raise
print 2
if __name__ == '__main__':
foo()
Any official documentation for this type of usage pattern?
As Russell said,
A bare
raise
statement re-raises the last caught exception.
It doesn't matter whether this is happening in a try-except block or not. If there has been a caught exception, then calling raise
will re-raise that exception. Otherwise, Python will complain that the previously caught exception is None
and raise a TypeError
because None
is not something that can actually be raised.
As tdelaney said, it doesn't seem to make sense to do this except in an error-handling function. Personally I'd say that it doesn't even belong in an error-handling function, as the raise
should still be in the except
clause. Someone could use this in an attempt to execute code whether or not an error occurs, but a finally
clause is the proper way to do that. Another possibility would be using this as a way to determine if an error occurred while executing the function, but there are much better ways to do that (such as returning an extra value that indicates if/where an error occurred).
A Bare raise reraises the current exception. This usually makes no sense at the end of a function, unless the function is called in an exception:
By itself, the raise is invalid and python throws its own exception
>>> def x():
... raise
>>> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType
But if called within an exception block, it acts sanely
>>> try:
... int('a')
... except:
... x()
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>>
EDIT
This might be a perfectly reasonable thing to do if the function is attempting some sort of recovery. The function could fix what's broken, log a message, trigger the fire extinguishers, etc... and raise
if it still thinks the system is in error.
A bare raise
statement re-raises the last caught exception. https://docs.python.org/2/tutorial/errors.html#raising-exceptions
From this documentation we can read:
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 TypeError exception is raised indicating that this is an error (if running under IDLE, a Queue.Empty exception is raised instead).
This means that, in the case of your code, if no exception occurs within the try ... except
block, then you are forcing the program to raise a TypeError exception to happen.
I had a problem like this where I needed to raise a previously caught exception outside the try/except block if my function didn't return a value. I did a bit of looking around in the sys
and traceback
modules, but couldn't find a good method to do this, so I just ended up storing the exception outside the block.
def foo():
caught = None
try:
raise Exception
except Exception as e:
caught = e
pass
raise caught
f = foo()
Traceback (most recent call last):
line 13, in <module>
line 10, in foo
line 5, in foo
Exception
Clearly this isn't useful in the above example, but it's pretty useful if you need to try something quite a few times in a loop and re-raise. My specific need was for an HTTP request retry mechanism.
import time
def foo(key):
caught = None
for i in [1, 2, 3, 4, 5]:
try:
return d[key]
except KeyError as e:
caught = e
print(i)
time.sleep(i)
continue
raise caught
d = {"bar": "baz"}
f = foo(key="baz")
1
2
3
4
5
Traceback (most recent call last):
line 19, in <module>
line 15, in foo
line 8, in foo
KeyError: 'baz'
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.