I am writing a long running function that should never die like this:
def immortal():
try:
# do something
except:
sleep(5)
immortal()
In this way, if there is something wrong in between try...except, it would be caught, after 5 seconds of sleep, the functions starts again.
What I am worrying about is, since it's a long running function, if there are two many errors, won't it cause the try...except stack too deep, and lead to performance problem?
Am I doing this right? If not, what's the correct way?
There is an optional else when using try... except.
def immortal():
while True:
try:
# pass or raise
except:
print('error')
else:
print('done')
break
Related
I am confused as to how should I use try-catch block with for loops. Is there any standard we should follow for this. These are some sample codes. Which one should be the preferred approach?
def func1():
try:
for i in range():
do_something()
except:
print(error)
def func1():
for i in range():
try:
do_something()
except:
print(error)
Or in case of using multiple for loops:
def func3():
try:
for i in range():
for j in range():
do_something()
except:
print(error)
def func4():
for i in range():
for j in range():
try:
do_something()
except:
print(error)
Depends on the condition, if you have a multiple for loop, and the function in the inner loop throws an error, do you want to continue running the for loop for other inputs, or you want to stop the for loop execution completely.
If you want to continue running the loop, then having the try catch inside the for loop makes sense like below, so that you still continue looping
As always, you can have a finally condition in either of your try-catch logic which might do something for you!
def func4():
for i in range():
for j in range():
try:
do_something()
except:
print(error)
But if you want to stop looping in case an exception happens, keeping the try-catch outside the loop makes sense
def func3():
try:
for i in range():
for j in range():
do_something()
except:
print(error)
The first approach does have a caveat where if you have a loop running 100 times, and the exception is thrown 10 times, maybe you need to handle it every time in a different way or suppress it, and you are not sure if more exceptions will be thrown down the line once more loops run. An example where catching exception inside a for loop is beneficial might will be if you are processing a list of lists, and some sublists have bad elements in it, and you want to ignore them and keep the res.t
Whereas in the second approach, you just stop on the first exception and give up on looping, which might be bad if your data size you are looping on is pretty big, and you need to restart the loop every time, but might be beneficial if you want to correct your dataset at the first error you see and run it again!
It depends on your situation.
If you need a complete success operation to continue, you may want to put the try/catch outside the loop.
If your results in loop won't effect each other, you can put the try/catch inside the loop.
For example, downloading contents from website (the loop won't break when error):
contents = []
for i in range(100):
try:
contents.append(requests.get("http://example.com/%d.html" % i))
except:
print("page %d is not available.", i)
Updating game or applications (break the loop when error):
updateList = ["File1.jpg", "File2.jpg"]
try:
for file in updateList:
res = requests.get("http://example.com/%s" % file)
except:
print("Update has failed, application cannot continue.")
I'm in trouble about how to end a 'try' loop, which is occurred since I have the 'try', here is the code:
import time
class exe_loc:
mem = ''
lib = ''
main = ''
def wizard():
while True:
try:
temp_me = input('Please specify the full directory of the memory, usually it will be a folder called "mem"> ' )
if temp_me is True:
exe_loc.mem = temp_me
time.sleep(1)
else:
print('Error value! Please run this configurator again!')
sys.exit()
temp_lib = input('Please specify the full directory of the library, usually it will be a folder called "lib"> ')
if temp_lib is True:
exe_loc.lib = temp_lib
time.sleep(1)
else:
print('Invalid value! Please run this configurator again!')
sys.exit()
temp_main = input('Please specify the full main executable directory, usually it will be app main directory> ')
if temp_main is True:
exe_loc.main = temp_main
time.sleep(1)
I tried end it by using break, pass, and I even leaves it empty what I get is Unexpected EOF while parsing, I searched online and they said it is caused when the code blocks were not completed. Please show me if any of my code is wrong, thanks.
Btw, I'm using python 3 and I don't know how to be more specific for this question, kindly ask me if you did not understand. Sorry for my poor english.
EDIT: Solved by removing the try because I'm not using it, but I still wanna know how to end a try loop properly, thanks.
Your problem isn't the break, it's the overall, high-level shape of your try clause.
A try requires either an except or a finally block. You have neither, which means your try clause is never actually complete. So python keeps looking for the next bit until it reaches EOF (End Of File), at which point it complains.
The python docs explain in more detail, but basically you need either:
try:
do_stuff_here()
finally:
do_cleanup_here() # always runs, even if the above raises an exception
or
try:
do_stuff_here()
except SomeException:
handle_exception_here() # if do_stuff_here raised a SomeException
(You can also have both the except and finally.) If you don't need either the cleanup or the exception handling, that's even easier: just get rid of the try altogether, and have the block go directly under that while True.
Finally, as a terminology thing: try is not a loop. A loop is a bit of code that gets executed multiple times -- it loops. The try gets executed once. It's a "clause," not a "loop."
You have to also 'catch' the exception with the except statement, otherwise the try has no use.
So if you do something like:
try:
# some code here
except Exception:
# What to do if specified error is encountered
This way if anywhere in your try block an exception is raised it will not break your code, but it will be catched by your except.
Right now I'm doing this:
try:
while True:
s = client.recv_into( buff, buff_size )
roll += buff.decode()
I repeatedly call client.recv_into until it raises an exception. Now, I know eventually, without a doubt, it will raise an exception...
Is there a cleaner way to do this? Is there some sort of loop-until-exception construct or a common way to format this?
There are two ways to do this:
Like you did
try:
while True:
s = client.recv_into( buff, buff_size )
roll += buff.decode()
except YourException:
pass
or
while True:
try:
s = client.recv_into( buff, buff_size )
roll += buff.decode()
except YourException:
break
Personally, I would prefer the second solution as the break keyword makes clear what is happening in case of the exception.
Secondly, you should only catch the exception you're awaiting (in my example YourException). Otherwise IOError, KeyboardInterrupt, SystemExit etc. will also be caught, hiding "real errors" and potentially blocking your program from exiting properly.
That appears to be the (pythonic) way to do it. Indeed, the Python itertools page gives the following recipe for iter_except (calls a function func until the desired exception occurs):
def iter_except(func, exception, first=None):
try:
if first is not None:
yield first()
while 1:
yield func()
except exception:
pass
which is almost exactly what you're done here (although you probably do want to add a except [ExceptionName] line in your try loop, as Nils mentioned).
I've got a function that often throws an exception (SSH over 3g).
I'd like to keep trying to run function() every 10 seconds until it succeeds (doesn't throw an exception).
As I see it, there are two options:
Nesting:
def nestwrapper():
try:
output = function()
except SSHException as e:
# Try again
sleep(10)
return nestwrapper()
return output
Looping: (updated)
It's been pointed out that the previous looping code was pretty unnecessary.
def loopwrapper():
while True:
try:
return function()
except SSHException as e:
sleep(10)
Is there a preferred method of doing this?
Is there an issue with nesting and the exception stack?
I would find a loop to be cleaner and more efficient here. If this is an automation job, the recursive method could hit python recursion limit (default is 1000 iirc, can check with sys.getrecursionlimit()).
Don't use status is False for your expression, because this is an identity comparison. Use while not status.
I would probably implement it slightly differently too, because I don't see any need for the two different functions here:
def function_with_retries():
while True:
try:
output = function()
except SSHException:
sleep(10)
else:
return output
I'm not sure it makes a heck of a lot of sense to specially wrap the function call twice. the exception is probably reasonable, and you're going to the extra step of retrying on that particular exception. What I mean is that the try/except is rather tightly involved with the retrying loop.
This is the way I normally do this:
def retry_something():
while True:
try:
return something()
except SomeSpecialError:
sleep(10)
The while True: is really exactly what you're up to, you're going to loop forever, or rather, until you actually manage to something(), and then return. There's no further need for a boolean flag of success, that's indicated by the normal case of the return statement (which politely escapes the loop).
Keep it simple.
function looper(f):
while 1:
try:
return f()
except SSHException, e:
sleep(10)
output = looper(<function to call>)
I know that is a weird question, and probably there is not an answer.
I'm trying to execute the rest of the try block after an exception was caught and the except block was executed.
Example:
[...]
try:
do.this()
do.that()
[...]
except:
foo.bar()
[...]
do.this() raise an exception managed by foo.bar(), then I would like to execute the code from do.that(). I know that there is not a GOTO statement, but maybe some kind of hack or workaround!
Thanks!
A try... except... block catches one exception. That's what it's for. It executes the code inside the try, and if an exception is raised, handles it in the except. You can't raise multiple exceptions inside the try.
This is deliberate: the point of the construction is that you need explicitly to handle the exceptions that occur. Returning to the end of the try violates this, because then the except statement handles more than one thing.
You should do:
try:
do.this()
except FailError:
clean.up()
try:
do.that()
except FailError:
clean.up()
so that any exception you raise is handled explicitly.
Use a finally block? Am I missing something?
[...]
try:
do.this()
except:
foo.bar()
[...]
finally:
do.that()
[...]
If you always need to execute foo.bar() why not just move it after the try/except block? Or maybe even to a finally: block.
One possibility is to write a code in such a way that you can re-execute it all when the error condition has been solved, e.g.:
while 1:
try:
complex_operation()
except X:
solve_problem()
continue
break
fcts = [do.this, do.that]
for fct in fcts:
try:
fct()
except:
foo.bar()
You need two try blocks, one for each statement in your current try block.
This doesn't scale up well, but for smaller blocks of code you could use a classic finite-state-machine:
states = [do.this, do.that]
state = 0
while state < len(states):
try:
states[state]()
except:
foo.bar()
state += 1
Here's another alternative. Handle the error condition with a callback, so that after fixing the problem you can continue. The callback would basically contain exactly the same code you would put in the except block.
As a silly example, let's say that the exception you want to handle is a missing file, and that you have a way to deal with that problem (a default file or whatever). fileRetriever is the callback that knows how to deal with the problem. Then you would write:
def myOp(fileRetriever):
f = acquireFile()
if not f:
f = fileRetriever()
# continue with your stuff...
f2 = acquireAnotherFile()
if not f2:
f2 = fileRetriever()
# more stuff...
myOp(magicalCallback)
Note: I've never seen this design used in practice, but in specific situations I guess it might be usable.