hello I am pretty new into python , but I am trying to handle errors, however when I try to ctrl + C or L I got input > ^Cerror which it should be only display error and not ^C or ^L how can I fix this ?
except KeyboardInterrupt:
print("error")
except Exception as e:
raise e
You can back up and overwrite it, but you can't "fix" it. That character comes from the keyboard echo of the symbiont terminal: your stdin processor is set to echo (print to screen) whatever is typed. That ^C couplet is printed by this I/O processing before your program gets to handle the exception. Thus, the \r option (or a sequence of backspaces, \b) is likely your best remedy.
import sys
try:
while True:
string = input("Show me something")
except KeyboardInterrupt:
print("\b\b error")
except Exception as e:
raise e
Output, with CTRL-C at keyboard:
Show me something error
If you want to wipe out the entire input line, use \r instead:
except KeyboardInterrupt:
print("\rerror", " "*80)
Output:
Show me something -- this line appears until I hit CTRL-C. Replaced by
error
I have nested exceptions handling in my code, when inner blocks do some stuff before re-raising the exception to upper layers.
Traceback always reports the line number that started the exception handling.
However, when running in UI debugger (Pydev/Eclipse) it stops on the outer exception block in some cases.
Consider the following code for example:
import sys
def f(a):
c=5/a
return c
def sub(d):
print("Entered sub(%d)" % d)
try:
print("Entered try #sub")
e = f(d)/(d-1)
return e
except:
print("Do some staff before re-raising the exception upwards")
raise
def main():
try:
print("Entered try #main")
d = int(sys.argv[1])
sub(d)
except:
print("Reached except block #main")
raise
if __name__ == '__main__':
main()
When running with argument = 0, the exception is caused at line#4 and the debugger stops on that line:
However, when running with argument = 1, the exception is caused at line#11 (as reported in the printed traceback) but the debugger stops at line#15.
Once the debugger stops at the incorrect location it is very difficult to watch internal variables and handle the error, especially when the code in the try block uses loops.
In Pydev->Manage Exceptions, I checked only the "suspend on uncaught exceptions".
There is a checkbox "Skip exceptions caught in same function" that seem related (because it seems like the debugger skipped the first exception in sub and stopped on "raise" statement which can be considered another exception in same function, although the documentation says that it should re-raise the same exception).
This checkbox is grayed out unless I first check "Suspend on caught exceptions*", but once enabling it the debugger gets stuck and does not stop anywhere...
Will appreciate your help.
-Moshe
Please have a look at the pseudo-code.
I am unable to catch exception in Scenario2
Scenario 1:
A.py
def fun1():
try:
ssh connection
do something1
do something2
session.write(cmd1) # Execute some commands
session.write(cmd2)
session.write(cmd3)
session.write(cmd4)
except RuntimeError as err:
print err
Do something with err
Further decision making based on err
Scenario 2:
B.py
def fun1():
try:
ssh connection
do something1
do something2
execute_commands(session)
except RuntimeError as err:
print err
Do something with err
Further decision making based on err
def execute_commands(session):
session.write(cmd1) # Execute some commands
session.write(cmd2)
session.write(cmd3)
session.write(cmd4)
In A.py, There is only one function which does everything. I know that while executing cmd1 to cmd4, it throws runtime error. A.py absolutely works fine.
In B.py, I've created another separate function to execute those commands separately.But here I'm not able to catch that run time error.In B.py, as execute_commands() is called it hangs there. It doesn't catch any exceptions.
How do i catch the same exception occurred in fun1() when execute_commands() is called ?
import SSHLibrary
session = SSHLibrary.SSHLibrary()
session.open_connection(self.ip, self.prompt)
session.login(self.username, self.password)
session.write(cmd1)
session.read_until("some pattern")
Runtimerror causing because of pattern mismatch. So, handling it in exception block and processing it further.
I have a piece of code in Python that seems to cause an error probabilistically because it is accessing a server and sometimes that server has a 500 internal server error. I want to keep trying until I do not get the error. My solution was:
while True:
try:
#code with possible error
except:
continue
else:
#the rest of the code
break
This seems like a hack to me. Is there a more Pythonic way to do this?
It won't get much cleaner. This is not a very clean thing to do. At best (which would be more readable anyway, since the condition for the break is up there with the while), you could create a variable result = None and loop while it is None. You should also adjust the variables and you can replace continue with the semantically perhaps correct pass (you don't care if an error occurs, you just want to ignore it) and drop the break - this also gets the rest of the code, which only executes once, out of the loop. Also note that bare except: clauses are evil for reasons given in the documentation.
Example incorporating all of the above:
result = None
while result is None:
try:
# connect
result = get_data(...)
except:
pass
# other code that uses result but is not involved in getting it
Here is one that hard fails after 4 attempts, and waits 2 seconds between attempts. Change as you wish to get what you want form this one:
from time import sleep
for x in range(0, 4): # try 4 times
try:
# msg.send()
# put your logic here
str_error = None
except Exception as str_error:
pass
if str_error:
sleep(2) # wait for 2 seconds before trying to fetch the data again
else:
break
Here is an example with backoff:
from time import sleep
sleep_time = 2
num_retries = 4
for x in range(0, num_retries):
try:
# put your logic here
str_error = None
except Exception as e:
str_error = str(e)
if str_error:
sleep(sleep_time) # wait before trying to fetch the data again
sleep_time *= 2 # Implement your backoff algorithm here i.e. exponential backoff
else:
break
Maybe something like this:
connected = False
while not connected:
try:
try_connect()
connected = True
except ...:
pass
When retrying due to error, you should always:
implement a retry limit, or you may get blocked on an infinite loop
implement a delay, or you'll hammer resources too hard, such as your CPU or the already distressed remote server
A simple generic way to solve this problem while covering those concerns would be to use the backoff library. A basic example:
import backoff
#backoff.on_exception(
backoff.expo,
MyException,
max_tries=5
)
def make_request(self, data):
# do the request
This code wraps make_request with a decorator which implements the retry logic. We retry whenever our specific error MyException occurs, with a limit of 5 retries. Exponential backoff is a good idea in this context to help minimize the additional burden our retries place on the remote server.
The itertools.iter_except recipes encapsulates this idea of "calling a function repeatedly until an exception is raised". It is similar to the accepted answer, but the recipe gives an iterator instead.
From the recipes:
def iter_except(func, exception, first=None):
""" Call a function repeatedly until an exception is raised."""
try:
if first is not None:
yield first() # For database APIs needing an initial cast to db.first()
while True:
yield func()
except exception:
pass
You can certainly implement the latter code directly. For convenience, I use a separate library, more_itertools, that implements this recipe for us (optional).
Code
import more_itertools as mit
list(mit.iter_except([0, 1, 2].pop, IndexError))
# [2, 1, 0]
Details
Here the pop method (or given function) is called for every iteration of the list object until an IndexError is raised.
For your case, given some connect_function and expected error, you can make an iterator that calls the function repeatedly until an exception is raised, e.g.
mit.iter_except(connect_function, ConnectionError)
At this point, treat it as any other iterator by looping over it or calling next().
Here's an utility function that I wrote to wrap the retry until success into a neater package. It uses the same basic structure, but prevents repetition. It could be modified to catch and rethrow the exception on the final try relatively easily.
def try_until(func, max_tries, sleep_time):
for _ in range(0,max_tries):
try:
return func()
except:
sleep(sleep_time)
raise WellNamedException()
#could be 'return sensibleDefaultValue'
Can then be called like this
result = try_until(my_function, 100, 1000)
If you need to pass arguments to my_function, you can either do this by having try_until forward the arguments, or by wrapping it in a no argument lambda:
result = try_until(lambda : my_function(x,y,z), 100, 1000)
Maybe decorator based?
You can pass as decorator arguments list of exceptions on which we want to retry and/or number of tries.
def retry(exceptions=None, tries=None):
if exceptions:
exceptions = tuple(exceptions)
def wrapper(fun):
def retry_calls(*args, **kwargs):
if tries:
for _ in xrange(tries):
try:
fun(*args, **kwargs)
except exceptions:
pass
else:
break
else:
while True:
try:
fun(*args, **kwargs)
except exceptions:
pass
else:
break
return retry_calls
return wrapper
from random import randint
#retry([NameError, ValueError])
def foo():
if randint(0, 1):
raise NameError('FAIL!')
print 'Success'
#retry([ValueError], 2)
def bar():
if randint(0, 1):
raise ValueError('FAIL!')
print 'Success'
#retry([ValueError], 2)
def baz():
while True:
raise ValueError('FAIL!')
foo()
bar()
baz()
of course the 'try' part should be moved to another funcion becouse we using it in both loops but it's just example;)
Like most of the others, I'd recommend trying a finite number of times and sleeping between attempts. This way, you don't find yourself in an infinite loop in case something were to actually happen to the remote server.
I'd also recommend continuing only when you get the specific exception you're expecting. This way, you can still handle exceptions you might not expect.
from urllib.error import HTTPError
import traceback
from time import sleep
attempts = 10
while attempts > 0:
try:
#code with possible error
except HTTPError:
attempts -= 1
sleep(1)
continue
except:
print(traceback.format_exc())
#the rest of the code
break
Also, you don't need an else block. Because of the continue in the except block, you skip the rest of the loop until the try block works, the while condition gets satisfied, or an exception other than HTTPError comes up.
what about the retrying library on pypi?
I have been using it for a while and it does exactly what I want and more (retry on error, retry when None, retry with timeout). Below is example from their website:
import random
from retrying import retry
#retry
def do_something_unreliable():
if random.randint(0, 10) > 1:
raise IOError("Broken sauce, everything is hosed!!!111one")
else:
return "Awesome sauce!"
print do_something_unreliable()
e = ''
while e == '':
try:
response = ur.urlopen('https://https://raw.githubusercontent.com/MrMe42/Joe-Bot-Home-Assistant/mac/Joe.py')
e = ' '
except:
print('Connection refused. Retrying...')
time.sleep(1)
This should work. It sets e to '' and the while loop checks to see if it is still ''. If there is an error caught be the try statement, it prints that the connection was refused, waits 1 second and then starts over. It will keep going until there is no error in try, which then sets e to ' ', which kills the while loop.
Im attempting this now, this is what i came up with;
placeholder = 1
while placeholder is not None:
try:
#Code
placeholder = None
except Exception as e:
print(str(datetime.time(datetime.now()))[:8] + str(e)) #To log the errors
placeholder = e
time.sleep(0.5)
continue
Here is a short piece of code I use to capture the error as a string. Will retry till it succeeds. This catches all exceptions but you can change this as you wish.
start = 0
str_error = "Not executed yet."
while str_error:
try:
# replace line below with your logic , i.e. time out, max attempts
start = raw_input("enter a number, 0 for fail, last was {0}: ".format(start))
new_val = 5/int(start)
str_error=None
except Exception as str_error:
pass
WARNING: This code will be stuck in a forever loop until no exception occurs. This is just a simple example and MIGHT require you to break out of the loop sooner or sleep between retries.
How can you have a function or something that will be executed before your program quits? I have a script that will be constantly running in the background, and I need it to save some data to a file before it exits. Is there a standard way of doing this?
Check out the atexit module:
http://docs.python.org/library/atexit.html
For example, if I wanted to print a message when my application was terminating:
import atexit
def exit_handler():
print 'My application is ending!'
atexit.register(exit_handler)
Just be aware that this works great for normal termination of the script, but it won't get called in all cases (e.g. fatal internal errors).
If you want something to always run, even on errors, use try: finally: like this -
def main():
try:
execute_app()
finally:
handle_cleanup()
if __name__=='__main__':
main()
If you want to also handle exceptions you can insert an except: before the finally:
If you stop the script by raising a KeyboardInterrupt (e.g. by pressing Ctrl-C), you can catch that just as a standard exception. You can also catch SystemExit in the same way.
try:
...
except KeyboardInterrupt:
# clean up
raise
I mention this just so that you know about it; the 'right' way to do this is the atexit module mentioned above.
If you have class objects, that exists during the whole lifetime of the program, you can also execute commands from the classes with the __del__(self) method:
class x:
def __init__(self):
while True:
print ("running")
sleep(1)
def __del__(self):
print("destructuring")
a = x()
this works on normal program end as well if the execution is aborted, for sure there will be some exceptions:
running
running
running
running
running
Traceback (most recent call last):
File "x.py", line 14, in <module>
a = x()
File "x.py", line 8, in __init__
sleep(1)
KeyboardInterrupt
destructuring
This is a version adapted from other answers.
It should work (not fully tested) with graceful exits, kills, and PyCharm stop button (the last one I can confirm).
import signal
import atexit
def handle_exit(*args):
try:
... do computation ...
except BaseException as exception:
... handle the exception ...
atexit.register(handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)