Exception Handling in Python for continuous execution - python

The question is related to Python:
Normally, I use except(RuntimeError) and use continue, so my code does not break while processing huge amounts of data.
However, it is harder for me to include all the types of errors that I encounter while running my code, since there are multiple possibilities. How do I just say - whatever happens - don't break but just continue, instead of including (RuntimeError, TypeError, ValueError and so on)

Have you tried using only except with no parameters?
try:
code
except:
continue

Related

How to complete process by handling the error?

-This is a Python in general question.
I am having topology errors very often, they are very small and i would like to proceed to intersection even though they are there. Is it possible to make an exception for this particular :
TopologyException: found non-noded intersection between LINESTRING (229971 4.39944e+06, 229971 4.39944e+06) and LINESTRING (229971 4.39944e+06, 229971 4.39944e+06) at 229971.08857010119 4399438.0928708706 and make it complete the process anyway? I am using Python and Geopandas.
Also sometimes in intersection it says:
TopologicalError: This operation could not be performed. Reason: unknown
is it possible for any line like this:inte_s=gpd.overlay(data2,asttom,how='intersection')
that is causing this Error to create an exception and make it perform the calculation by being unfazed from the error that would show up? What code would do that in this line where the intersection is done?
Yes, you can skip or handle any exception in python using try/except blocks. In your case it would be:
try:
inte_s=gpd.overlay(data2,asttom,how='intersection')
except (TopologicalError, TopologyException):
#skipping error here
pass
TopologicalError needs to imported first, then use a try...except statement.
from shapely.geos import TopologicalError
try:
# your code that may raise the exception
except TopologicalError:
# alternative code if the exception is raised
One way you can handle errors in Python is using a try and except statement.
Here is a sample piece of code that I use often when testing. You can place the operation that might fail in the try part of the block, and even if it does throw an exception, your whole script will not be broken.
try:
#operation that may fail
except Exception as e:
print('something went wrong: ' + e)
# what you want to do if the operation does fail
The above code is a general form for a try/except statement. If you are looking to catch a specific error, you're looking for something like this SO answer.

multiple try catch blocks in a loop

Am I being stupid for doing something like this? I feel like I may not fundamentally understand the purpose of try catch blocks.
I have a script that I want to run on auto-pilot on a daemon and what happens sometimes is that it checks to see if some resources in a list are fully allocated or not. If the resource is fully allocated it cannot continue with one thing, but there is other stuff it can do. Because I'm also calling something from an API, sometimes the Exception thrown by the API is very general (just like API_Exception). Is doing multiple try blocks pointless in this situation?
The main issue is that the break doesn't allow me to get out of the loop
for:
try:
stuff()
except ExceptionA:
handle()
break
except ExceptionB:
report()
sys.exit()
try:
other_stuff()
except ExceptionA:
handle_in_a_different_way()
break
except ExceptionC:
report()
sys.exit()
other_code_that_should_execute_if_there_is_a_break()
In this case, should I be just combine these two blocks and catch ExceptionA once? ExceptionA might not have easily parseable parameters.
for:
try:
stuff()
other_stuff()
except ExceptionA:
if ExceptionA has param
handle()
elif ExceptionA has other param
handle_in_a_different_way()
except ExceptionB:
report()
sys.exit()
except ExceptionC:
report()
sys.exit()
I m not very experienced in exceptions, but I found something in the stack that may be helpfull.
Catch multiple exceptions in one line (except block)
It also depends on which version you are currently using, in python 2 it seems you can use a comma to separate the exceptions, but in python 3 people advise to use 'as'to set them in a variable, then you could verify how to treat them

Most reliable way of exiting out of a function on a failed try

What is the best way to except out of ALL potential errors?
## Try to...
try:
## Print
print "hi"
## On failure to get data
except Exception:
## Exit out of current function
return
or
## Try to...
try:
## Print
print "hi"
## On failure to get data
except:
## Exit out of current function
return
or are there better ways?
Thanks in advance
- Hyflex
Generally, always catch specific errors you know will occur. Especially if you catch everything, (That is, except:) you will catch KeyboardInterrupt and make your program not be stoppable by Ctrl+C; SystemExit that is used to kill a thread, and so forth... While catching Exception is slightly better, it will still lose too much context; the exceptional condition that occurs might be other than you expected. Thus always catch IOError, ValueError, TypeError and so forth, by their names.
Update
There is 1 case where you want to use except Exception; at a top level of a program, or an action where you want to make sure that the whole program does not crash due to an uncaught Exception.
Never use a bare except:. If you do, you'll wind up catching things like SystemExit and KeyboardInterrupt, which are not intended to be caught in most code.
Ideally, you should try to be as specific as possible - for example, catching IOError for a failing print. If you can't predict exactly what exceptions you're concerned about, then at the very least you should use except Exception to avoid the aforementioned problem.

Guidance on exceptions given by the Python docs

According to the Python documentation on idioms and anti-idioms in relation to exceptions: "You should try to use as few except clauses in your code as you can — the ones you do use will usually be inside calls which should always succeed, or a catch-all in a main function." Taking this sentence in sections...
"You should try to use as few except clauses in your code as you can"
A bit confusing for a newbie like myself, I thought it was good practise in Python to use the EAFP style -i.e. many try and except statements. Or am I missing the point?
"the ones you do use will usually be inside calls which should always succeed"
I don't understand the point that's being made here.
"or a catch-all in a main function."
So it's good style to any let code that throws an exception to simply pass it up the call stack until it reaches the top level where you have really generic exception handling?
"You should try to use as few except clauses in your code as you can"
It's easy to litter your code with exceptions:
def solve_linear(mat1, mat2):
det1 = determinant(mat1)
det2 = determinant(mat2)
try:
return det1 / det2
except ZeroDivisionError:
raise NoSolution
Here, it's probably fine to let the ZeroDivisionError propagate. You don't need to catch it.
"the ones you do use will usually be inside calls which should always succeed"
For example, look at this code which reads a file, or returns a cached value. It normally succeeds, in spite of the KeyError exception:
def read_file(path):
try:
return cache[path]
except KeyError:
fp = open(path, 'rb')
data = fp.read()
fp.close()
cache[path] = data
return data
"or a catch-all in a main function."
If your program is interactive, you'll probably want to catch almost everything at the top level. Here's the top loop of an interactive command-line program:
def main():
while True:
try:
text = raw_input('enter command: ')
cmd = parse_command(text)
except EOFError:
return
except KeyboardInterrupt:
return
except ValueError:
print 'Syntax error'
continue
try:
run_cmd(cmd)
except SystemExit:
raise
except Exception:
traceback.print_exc()
Concerning the first point, the whole point of using exceptions is that you don't have to wrap every line in one! E.g. in C, errors are usually determined by the return value of a function call. So you have to check those after every call if you want to catch all errors. With Python you can group a (possibly large) block of statements that go together in a try/except block and only deal with all errors once.
The second point is that (if possible) you want to solve failures close to the point where they occur. E.g. you are reading data from a network and get zero bytes. In that case it is usually perfectly allright to wait and try again.
The last point is that sometimes an error is so big that it cannot be handled at a low level. E.g. if you are trying to open a file that not exist, it wil fail. And your program cannot do whatever it was going to do with the contents of the file. It is best to handle that at the top level of the program and ask the user for another file name or maybe quit the program.
I think the point is that exceptions should be used only for 'exceptional' circumstances. That is the meaning behind the use "in calls which will usually succeed". An example of this might be some computation that under some really weird circumstances ends having to do a division by zero. Then you can enclose that in a try / except statement to deal with that possibility.
The catch-all in a main function would be applicable to the same scenario. Say your calculations end up with a division by zero somewhere deep in the call stack. From this point you can't continue, so there's no point in having a try/except statement right at the point of failure. It would make more sense to just have one at a higher level where you can reasonably recover from the error.
The example they give in the documentation is an example of this. When calling 'get_status' you would expect the file to be there. If it doesn't then you have the except statement to deal with that (although, as mentioned, in that particular case the 'with' statement is much better).
The Python philosophy is typically to "ask forgiveness, not permission." But the idea isn't to use a try-except clause to catch ALL possible errors. Ideally, each try-except will only catch the error(s) that are relevant.
BAD (doesn't specify a specific exception type):
a = [1, 2, 3]
i = 3
try:
print a[i]
except:
print "Not found!"
GOOD (only handles the exception we expect to get):
a = [1, 2, 3]
i = 3
try:
print a[i]
except IndexError:
print "Not found!"
The reason this is important is so we don't obscure other possible code errors. What if, in this example, i was 1.8? The first example would print Not Found!, obscuring the real issue, but the second example would return TypeError: list indices must be integers, not float letting us know that there's a logical flaw in our code.

Python Ignore Exception and Go Back to Where I Was

I know using below code to ignore a certain exception, but how to let the code go back to where it got exception and keep executing? Say if the exception 'Exception' raises in do_something1, how to make the code ignore it and keep finishing do_something1 and process do_something2? My code just go to finally block after process pass in except block. Please advise, thanks.
try:
do_something1
do_something2
do_something3
do_something4
except Exception:
pass
finally:
clean_up
EDIT:
Thanks for the reply. Now I know what's the correct way to do it. But here's another question, can I just ignore a specific exception (say if I know the error number). Is below code possible?
try:
do_something1
except Exception.strerror == 10001:
pass
try:
do_something2
except Exception.strerror == 10002:
pass
finally:
clean_up
do_something3
do_something4
There's no direct way for the code to go back inside the try-except block. If, however, you're looking at trying to execute these different independant actions and keep executing when one fails (without copy/pasting the try/except block), you're going to have to write something like this:
actions = (
do_something1, do_something2, #...
)
for action in actions:
try:
action()
except Exception, error:
pass
update. The way to ignore specific exceptions is to catch the type of exception that you want, test it to see if you want to ignore it and re-raise it if you dont.
try:
do_something1
except TheExceptionTypeThatICanHandleError, e:
if e.strerror != 10001:
raise
finally:
clean_up
Note also, that each try statement needs its own finally clause if you want it to have one. It wont 'attach itself' to the previous try statement. A raise statement with nothing else is the correct way to re-raise the last exception. Don't let anybody tell you otherwise.
What you want are continuations which python doesn't natively provide. Beyond that, the answer to your question depends on exactly what you want to do. If you want do_something1 to continue regardless of exceptions, then it would have to catch the exceptions and ignore them itself.
if you just want do_something2 to happen regardless of if do_something1 completes, you need a separate try statement for each one.
try:
do_something1()
except:
pass
try:
do_something2()
except:
pass
etc. If you can provide a more detailed example of what it is that you want to do, then there is a good chance that myself or someone smarter than myself can either help you or (more likely) talk you out of it and suggest a more reasonable alternative.
This is pretty much missing the point of exceptions.
If the first statement has thrown an exception, the system is in an indeterminate state and you have to treat the following statement as unsafe to run.
If you know which statements might fail, and how they might fail, then you can use exception handling to specifically clean up the problems which might occur with a particular block of statements before moving on to the next section.
So, the only real answer is to handle exceptions around each set of statements that you want to treat as atomic
you could have all of the do_something's in a list, and iterate through them like this, so it's no so wordy. You can use lambda functions instead if you require arguments for the working functions
work = [lambda: dosomething1(args), dosomething2, lambda: dosomething3(*kw, **kwargs)]
for each in work:
try:
each()
except:
pass
cleanup()
Exceptions are usually raised when a performing task can not be completed in a manner intended by the code due to certain reasons. This is usually raised as exceptions. Exceptions should be handled and not ignored. The whole idea of exception is that the program can not continue in the normal execution flow without abnormal results.
What if you write a code to open a file and read it? What if this file does not exist?
It is much better to raise exception. You can not read a file where none exists. What you can do is handle the exception, let the user know that no such file exists. What advantage would be obtained for continuing to read the file when a file could not be opened at all.
In fact the above answers provided by Aaron works on the principle of handling your exceptions.
I posted this recently as an answer to another question. Here you have a function that returns a function that ignores ("traps") specified exceptions when calling any function. Then you invoke the desired function indirectly through the "trap."
def maketrap(*exceptions):
def trap(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except exceptions:
return None
return trap
# create a trap that ignores all exceptions
trapall = maketrap(Exception)
# create a trap that ignores two exceptions
trapkeyattrerr = maketrap(KeyError, AttributeError)
# Now call some functions, ignoring specific exceptions
trapall(dosomething1, arg1, arg2)
trapkeyattrerr(dosomething2, arg1, arg2, arg3)
In general I'm with those who say that ignoring exceptions is a bad idea, but if you do it, you should be as specific as possible as to which exceptions you think your code can tolerate.
Python 3.4 added contextlib.suppress(), a context manager that takes a list of exceptions and suppresses them within the context:
with contextlib.suppress(IOError):
print('inside')
print(pathlib.Path('myfile').read_text()) # Boom
print('inside end')
print('outside')
Note that, just as with regular try/except, an exception within the context causes the rest of the context to be skipped. So, if an exception happens in the line commented with Boom, the output will be:
inside
outside

Categories