Suppose the following code.
try:
some_code_1
except: # will it be called twice, if an error occures in finally?
some_code_2
finally:
some_code_3
Suppose an exception occurs in some_code_3. Do I need an extra try-except clause around some_code_3 (see below) or will the exception with some_code_2 be called again, which in principle could cause an infinite loop?
Is this saver?
try:
some_code_1
except: # will it be called twice, if an error occures in finally?
some_code_2
finally:
try:
some_code_3
except:
pass
Just give it a try:
try:
print(abc) #Will raise NameError
except:
print("In exception")
finally:
print(xyz) #Will raise NameError
Output:
In exception
Traceback (most recent call last):
File "Z:/test/test.py", line 7, in <module>
print(xyz)
NameError: name 'xyz' is not defined
So no, it doesn't end up in an infinite loop
python doesn't go back in the execution flow, but rather statement by statement.
By the time it reaches finally, if an error is thrown there, it needs yet another handle
The finally in your sample code will not catch exception from some_code_3.
whether it's needed to catch exception from some_code_3 depends on your design.
Related
def strornum(a):
try:
return(a/1)
except Exception:
return("ERROR")
bob=strornum("W")
print(bob)
This gives me the correct error of "ERROR"
def strornum(a):
try:
return(a/1)
except Exception:
return("ERROR")
bob=strornum(W)
print(bob)
This is not handled and gives me "NameError: name 'W' is not defined"
I need to capture this error
Any ideas?
What you want is not possible.
When you call a function, all the arguments are evaluated before the code in the function is executed. Python doesn't wait until you refer to the parameter variable inside the function (there are some languages that do this, it's called "lazy evaluation").
So the error is raised in the calling code, before entering your try/except block, so it can't catch it there.
Running the failing code gives the traceback message
Traceback (most recent call last):
File "test.py", line 7, in <module>
bob=strornum(W)
NameError: name 'W' is not defined
The error was raised when you tried to call the function, not in the function itself. W is not defined at the point of the call. The solution is to add another exception handler at that level.
def strornum(a):
try:
return(a/1)
except Exception:
return("ERROR")
try:
bob=strornum(W)
print(bob)
except Exception:
print("Outer Error")
obligatory warning: Catching all exceptions is usually not a good idea because it can mask real problems with your code.
Background:when i call many library function, one of them raised an
exception, i want to know which call in my code raised it, but the
call chain is very deep, it's hard to find which line, in my code,
raised the exception.
How to get the line number which raised an exception in the frame main(), when i call do_something1(), it called a very deeply subframe and caused an exception, this make me hard to find which line raised the exception in the frame main() when i print the error information.
def do_somethingN():
raise Exception("some error happened")
def do_something1():
# do_something1 call do_something2, do_something2 call do_something3 ...
do_somethingN()
def main():
import traceback
try:
do_something1()
except Exception as e:
tb = traceback.format_exc()
print(tb)
main()
I am writing a little software for executing python codes and I want to print exceptions. The following function gets executed:
def run(self, mode='activate'):
try:
exec(self.mycode)
except Exception:
print(traceback.format_exc())
There is no information about what exactly will be executed in the exec() function, it can literally be any python code. I want to print an exception thrown (mostly automatically by python due to code errors) somehow like shown, while executing via exec() including the line of code passed into the exec() function where the exception has been thrown.
I so far only managed to get the 'exec(mycode)' as exception code output, but I want the actual line of code that crashed in mycode.
try this :
def run(self, mode='activate'):
try:
exec(your_code)
except Exception as e:
print(e)
This would work!
add this line traceback.print_exc()
def run(self, mode='activate'):
try:
exec(your_code)
except Exception as e:
print(e)
traceback.print_exc()
This would give you the exception information and also will give you line number where the exception/error occurred!
Consider this example, with a deliberate typo:
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
The handling of the explicitly raised ValueError results in a NameError:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
ValueError: ?
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
NameError: name 'ValueErro' is not defined
However, if a ValueError is not raised:
try:
print("Hello!")
except ValueErro:
print("Error!")
finally:
print("World!")
then no exception occurs; Hello! and World! are simply printed.
Why is there no NameError caused by the typo ValueErro (no such name exists)? Shouldn't this have been detected ahead of time?
Can I use a different syntax to ensure that the problem is caught ahead of time?
After a comment from #DYZ, I found the right search terms to get the answer.
https://docs.python.org/3/tutorial/errors.html#handling-exceptions
The try statement works as follows.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
Another resource exploring this problem.
https://dbaktiar-on-python.blogspot.com/2009/07/python-lazy-evaluation-on-exception.html
-
My Solution moving forward:
# Explicitly bind the Exception Names in a non-lazy fashion.
errors = (KeyboardInterrupt, ValueErro) # Caught!
try:
print("Hello!")
raise ValueError("?")
except errors:
print("Error!")
finally:
print("World!")
-
tl;dr - The except clauses are entirely skipped if the try clauses executes without exception.
Exceptions can be defined at run time. Example:
myexcept.py contains:
class ValueErro(Exception):
pass
Your program slightly modified:
import_myexcept = False
if import_myexcept:
from myexcept import ValueErro
try:
print("Hello!")
raise ValueError("?")
except ValueErro:
print("Error!")
finally:
print("World!")
This behaves just like your program: NameError: name 'ValueErro' is not defined.
But change: import_myexcept = True, and by the time the except ValueErro: statement is encountered, the ValueErro exception is defined and no NameError occurs.
I am doing this:
try: self.failUnless(sel.is_text_present("F!")) #sel.is_text_present("F!") is false
except AssertionError, e:
print("x"+e+"y")
sys.exit()
it is printing nothing except xy. no class name or anything else. what does the error in AssertionError normally contain?
edit: apparently the user provides its own message. selenium generated many of these:
except AssertionError, e: self.verificationErrors.append(str(e))
without sending in a message at all, so it appends a bunch of empty strings to verificationErrors.
Don't catch the errors from assertions. All the assertions in the unittest module take a final parameter, msg, which is the message to be raised if the assertion fails. Put your debugging there if necessary.
Standard assert statement doesn't put anything into the AssertionError, it's the traceback that matters. There is a assert expr, msg variant that sets the error message, if you're using unittest, then the second argument of assertTrue (failUnless is deprecated) will do it.
Sounds like you want to use your assertions as debug statements in the event of a failure. This should help...
import traceback
try:
assert 1 == 2
except AssertionError:
traceback.print_exc()
This prints:
Traceback (most recent call last):
File "./foo.py", line 4, in <module>
assert 1 == 2