I am trying to trap error and let the code finish running.
In the code below, I "do Something." if fails, I want to print Error Msg
and continue running the second half.
What is happening is When an error occurs with the first section, The error statement print and
stops running. I would like the code to keep running past the first section.
if len(rows) > 0:
try:
print "Do something"
except:
print time.strftime("%H:%M:%S")
try:
print "Do somethings else"
except:
print time.strftime("%H:%M:%S")
Python's exceptions don't have a built-in restart capability to "continue running the second half". Instead, you just need to move the "unconditional, always do this" part out of the try-clause and into a finally-clause or outside the try-statement altogether.
P.S. It is usually ill-advised to swallow all exceptions with a bare except-clause. Instead, the usual best practice is to catch only the exceptions you know how to handle.
Can you programmatically determine if 'do Something' failed? If so, that's a better way to go rather than just relying on an exception handling mechanism. I see this anti-pattern a lot in .net code. Exceptions, in many languages, are intended for exceptional circumstances, not just error handling.
Keeping answer just to preserve comments for those who might think like I did.
Related
I have a script that is operating a physical device. There is a physical malfunction on the device that occurs sometimes and when it does, I want to reset the device and continue with the script. I have this:
while True:
do_device_control()
device_status = get_device_status()
if device_status == 'Fault':
reset_device()
It seems to me that a neater / more Pythonic approach would raise an Exception:
try:
while True:
do_device_control()
device_status = get_device_status()
if device_status == 'Fault':
raise DeviceFaultException()
except DeviceFaultException:
reset_device()
But as far as I can see, there is no way to resume the script after resetting the device. Is there a way to make Exception handling work for this situation, or a more Pythonic approach than what I'm currently using?
A common Python idiom is "Ask forgiveness rather than permission", which applies very well to your question. An implementation like the following would suffice:
while True:
try:
do_device_control()
except DeviceFaultException:
reset_device()
This should get similar behavior as to what is in your original block of code using if statements.
However, you probably noticed that I did not check the device_status in my code. This is because you should allow the do_device_control function to raise the exception if it is unable to complete its task. This allows you to handle exceptions at the time the actions are being executed.
In an environment where you are working with a device that is running asynchronously to your code, you may check the device status and it be fine. It then might fail between the check and your do_device_control function. This is one example of why the "ask forgiveness rather than permission" paradigm exists.
Of course, this example only works if you can expect the do_device_control function to throw some sort of exception or change it so that it does. If you cannot expect/change this behavior, your first code block with the if statement would be preferred over explicitly raising an exception just to immediately catch it within the same code block.
I guess I'm not the first asking this question, but I haven't found a solution that I could use/understand yet. And the issue is probably not as simple as i first expected.
I think it can be boiled down to two general questions:
1) Is there a way to avoid Python to stop when an error occur and just jump on to the next line of code in the script?
2) Is there a way to make Python execute a line of code if an error occurs? Like, if error then...
My concrete problem:
I have a very large program with a lot of functions and other stuff, which would take forever to adjust individually by using "try" for example (if i understand it correctly)
My program run as a large loop that gather information and keeps running. This means that it does not really matter to me, that my program fails multiple time as long as it keeps running. I can easily handle that some of the information is with error and would just like my program to take a note of it and keep going.
Is there a solution to this?
As you rightly pointed out, the try/catch block in Python is by far your best ally:
for i in range(N):
try: do_foo() ; except: do_other_foo()
try: do_bar() ; except: do_other_bar()
Alternatively, you could also use, in case you didn't need the Exception:
from contextlib import suppress
for i in range(N):
with suppress(Exception):
do_foo()
with suppress(Exception):
do_bar()
Your only possibility is to rely on the try/except clause. Keep in mind that the try/except may use also finally and else (see documentation:
try:
print("problematic code - error NOT raised")
except:
print("code that gets executed only if an error occurs")
else:
print("code that gets executed only if an error does not occur")
finally:
print("code that gets ALWAYS executed")
# OUTPUT:
# problematic code - error NOT raised
# code that gets executed only if an error does not occur
# code that gets ALWAYS executed
or, when an error is raised:
try:
print("problematic code - error raised!")
raise "Terrible, terrible error"
except:
print("code that gets executed only if an error occurs")
else:
print("code that gets executed only if an error does not occur")
finally:
print("code that gets ALWAYS executed")
# OUTPUT:
# problematic code - error raised!
# code that gets executed only if an error occurs
# code that gets ALWAYS executed
I urge to point out, by the way, that ignoring everything makes me shiver:
you really should (at least, more or less) identify which exception can be raised, catch them (except ArithmeticError: ..., check built-in exceptions) and handle them individually. What you're trying to do will probably snowball into an endless chain of problems, and ignoring them will probably create more problems!
I think that this question helps to understand what a robust software is, meanwhile on this one you can see how SO community thinks python exceptions should be handled
I have a piece of code which is not in a function, say
x = 5
y = 10
if x > 5:
print("stopping")
What can I put after the print statement to stop the code from running further? Sys.exit() works, but raises an error that I don't want in the program. I want it to quietly stop the code as if it had reached the end of the main loop. Thanks.
As JBernardo pointed out, sys.exit() raises an exception. This exception is SystemExit. When it is not handled by the user code, the interpreter exits cleanly (a debugger debugging the program can catch it and keep control of the program, thanks to this mechanism, for instance)—as opposed to os._exit(), which is an unconditional abortion of the program.
This exception is not caught by except Exception:, because SystemExit does not inherit from Exception. However, it is caught by a naked except: clause.
So, if your program sees an exception, you may want to catch fewer exceptions by using except Exception: instead of except:. That said, catching all exceptions is discouraged, because this might hide real problems, so avoid it if you can, by making the except clause (if any) more specific.
My understanding of why this SystemExit exception mechanism is useful is that the user code goes through any finally clause after a sys.exit() found in an except clause: files can be closed cleanly, etc.; then the interpreter catches any SystemExit that was not caught by the user and exits for good (a debugger would instead catch it so as to keep the interpreter running and obtain information about the program that exited).
You can do what you're looking for by doing this:
import os
os._exit(1)
sys.exit() which is equivalent to sys.exit(0) means exit with success. sys.exit(1) or sys.exit("Some message") means exit with failure. Both cases raise a SystemExit exception. In fact when your program exists normally it is exactly like sys.exit(0) has been called.
When I ran across this thread, I was looking for a way to exit the program without an error, without an exception, have the code show as 'PASSED', and continue running other tests files. The solution, for me, was to use the return statement.
.
.
.
if re.match("^[\s\S]*gdm-simple-slave[\s\S]*$", driver.find_element_by_css_selector("BODY").text) == None:
print "Identifiers object gdm-simple-slave not listed in table"
return
else:
driver.find_element_by_xpath("//input[#value='gdm-simple-slave']").click()
.
.
.
That allowed me to run multiple programs while keeping the debugger running...
test_logsIdentifiersApache2EventWindow.py#16::test_LogsIdentifiersApache2EventWi
ndow **PASSED**
test_logsIdentifiersAudispdEventWindow.py#16::test_LogsIdentifiersAudispdEventWi
ndow **PASSED**
test_logsIdentifiersGdmSimpleSlaveEventWindow.py#16::test_LogsIdentifiersGdmSimp
leSlaveEventWindow Identifiers object gdm-simple-slave not listed in table
**PASSED**
test_logsIdentifiersAuditdEventWindow.py#16::test_LogsIdentifiersAuditdEventWind
ow **PASSED**
Use try-except statements.
a = [1, 2, 3, 4, 5]
for x in xrange(0,5):
try:
print a[x+1] #this is a faulty statement for test purposes
except:
exit()
print "This is the end of the program."
Output:
> python test.py
2
3
4
5
No errors printed, despite the error raised.
Is it bad form to exit() from within function?
def respond_OK():
sys.stdout.write('action=OK\n\n')
sys.stdout.flush() # redundant when followed by exit()
sys.exit(0)
Rather than setting an exit code and exit()ing from the __main__ name space?
def respond_OK():
global exit_status
sys.stdout.write('action=OK\n\n')
sys.stdout.flush()
exit_status = 0
sys.exit(exit_status)
The difference is negligible from a function perspective, just wondered what the consensus is on form. If you found the prior in someone else's code, would you look at it twice?
I would prefer to see an exception raised and handled from a main entry point, the type of which is translated into the exit code. Subclassing exceptions is so simple in python it's almost fun.
As posted in this answer's comments: Using sys.exit also means that the point of termination needs to know the actual status code, as opposed to the kind of error it encountered. Though that could be solved by an set of constants, of course. Using exceptions has other advantages, though: if one method fails, you could try another without re-entry, or print some post-mortem debugging info.
It makes no difference in terms of functionality, but it will likely make your code harder to follow, unless you take appropriate steps, e.g. commenting each of the calls from the main namespace which could lead to an exit.
Update: Note #mgilson's answer re the effect of catching an exception [It is possible to catch the exception that system.exit raises, and thus prevent exit]. You could make your code even more confusing that way.
Update 2: Note #sapht's suggestion to use an exception to orchestrate an exit. This is good advice, if you really want to do a non-local exit. Much better than setting a global.
There are a few cases where it's reasonably idiomatic.
If the user gives you bad command-line arguments, instead of this:
def usage(arg0):
print ... % (arg0,)
return 2
if __name__ == '__main__':
if ...:
sys.exit(usage(sys.argv[0]))
You often see this:
def usage():
print ... % (sys.argv[0],)
sys.exit(2)
if __name__ == '__main__':
if ...:
usage()
The only other common case I can think of is where initializing some library (via ctypes or a low-level C extension module) fails unexpectedly and leaves you in a state you can't reason about, so you just want to get out as soon as possible (e.g., to reduce the chance of segfaulting or printing garbage) For example:
if libfoo.initialize() != 0:
sys.exit(1)
Some might object to that because sys.exit doesn't actually bail out of the interpreter as soon as possible (it throws and catches an exception), so it's a false sense of safety. But you still see it reasonably often.
import sys
def checkarg():
try:
filename=str(sys.argv[1])
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
except:
print "ERROR"
sys.exit()
Hello all...i have a problem with the code above. When i call the 'checkarg' function, if i did not pass any parameter on the command line i have the "ERROR" output and sys exit, just as expected.
But, if i provide a parameter on the command line (like "-mycommand") it prints the "SPECIFIC_TEXT" and then prints "ERROR" message from the EXCEPT block too.
The TRY block will only run when I provide a parameter, if I don't, then EXCEPT will get the turn. But, it is running the TRY and EXCEPT blocks together.
Does anybody knows the reason of this behavior?? Any mistake on my code? Tks for all !
I think I understand your question...
sys.exit() exits by raising a SystemExit exception, which your except statement is catching.
Answer found here: http://docs.python.org/library/sys.html
sys.exit([arg])
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
sys.exit works by raising an exception. That's why your except block executes.
You really shouldn't be using try/except for situations where you can check the state using control flow logic.
Instead, in this case, check for if len(sys.argv) > 1.
Another reason never to use specifically a blank except: You will catch even system exceptions like SystemExit or KeyboardInterrupt, making it potentially impossible to terminate your program short of a messy kill.
I know you've already accepted an answer, but I think the root of the problem is that your try block contains code in which you do not necessarily wish to catch exceptions; rather, you merely wish these statements to be executed after the code in which you wish to catch exceptions if no exception occurs.
To address this, your try block should contain only filename=str(sys.argv[1]) and the rest of the code now in your try block should be moved to an else block, which will be executed only if no exception occurs. In other words:
try:
filename=str(sys.argv[1])
except:
print "ERROR"
sys.exit()
else:
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
Or in this case, since you exit the script entirely in the case of an exception, you don't actually need the else:
try:
filename=str(sys.argv[1])
except:
print "ERROR"
sys.exit()
if filename=="-mycommand":
print "SPECIFIC_TEXT"
sys.exit()
else:
return filename
The fact that you're catching every exception with your bare except is bad style and changing that would also avoid the problem, but to me, it's secondary. You do not wish to catch exceptions in your if/else code, so it should not be in the try block to begin with. IMHO, most admonitions against bare except would be moot if this guideline were followed more closely.