Avoid nested try/except - python

I have the following code structure:
try:
x = function_one(args)
try:
y = function_two(args)
try:
#
# some code where I need x and y
#
except Exception as e::
print("Problem with code above : ", e)
except Exception as e:
print("Problem with function_two : ", e)
#
# some code here
#
except Exception as e:
print("Problem with function_one : ", e)
It works but i was wondering if i can avoid this nested try/exception ?
For example if x is empty and can't be used after, would it be better to put the try / except inside function_one and find a solution to check if i can use x for the rest of the code, and if not, stop the code ?
I could do a if x something but it creates also nested part.

If your exception block is not doing something functional(proceeding with the rest of the code if it even has an error inside), you shouldn't use a nested try-catch block. Instead, you can write more exception blocks. For example,
try:
x = function_one(args)
y = function_two(args)
except Exceptionx as e:
print("Problem with function_one : ", e)
except Exceptiony as e:
print("Problem with function_two : ", e)
The Exceptionx and Exceptiony should be Exception class object and you should know that what kind of exception you would get. You can learn more examples at
https://docs.python.org/3/tutorial/errors.html

If you're only checking a certain block of code with a try\except, you can just wrap that block in the handler:
try:
x = function_one(args)
except Exception as e:
print("Problem with function_one : ", e)
try:
y = function_two(args)
except Exception as e:
print("Problem with function_two : ", e)
try:
#
# some code where I need x and y
#
except Exception as e::
print("Problem with code above : ", e)
try:
#
# some code here
#
except Exception as e::
print("Problem with code above : ", e)
In general, only nest exception blocks if you plan to handle a more specific error in the inner block.

If the reason for the different except blocks is to better understand where the error occurred, you can just wrap the whole block in a single try-except block and print the traceback:
import traceback
try:
x = function_one(args)
y = function_two(args)
except:
traceback.print_exc()

Related

How can I catch an exception raised inside of a catch clause, If the finally clause corresponding to the catch clause contains a return statement?

Suppose that:
TEF is a try-except-finally block.
an exception is raised from within the try clause of TEF
The finally clause, F of block T contains a return statement
TEF contains an except clause E
an exception e is raised inside of E
How can we catch e from outside of clause F and outside of clause E?
If that was confusing, then some code is shown below:
def e():
out = "hello world"
try:
raise ValueError("my name is Sarah")
except BaseException as exc:
# HOW DO I CATCH THE FIRST OF THE FOLLOWING
# exceptions from outside of this, current,
# except clause?
raise ValueError("secret info it would be good to know")
raise AttributeError
raise type("Hell", (Exception,), dict())()
[0, 1, 2][99999]
class AnythingYouCanThinkOf(Exception):
pass
raise AnythingYouCanThinkOf
out = "definitely not `hello world`"
finally:
return out
print(e())
print("No error!!! wowza!")
The code above prints:
hello world
No error!!! wowza!
If we comment out the line out = "hello world" then we get UnboundLocalError: local variable 'out' referenced before assignment. However, I am still not sure how to recover ValueError("secret info it would be good to know")
Also, if you put almost the same code outside of the function e, you get very different results. Why?
if True:
out = "hello world"
try:
raise ValueError("my name is Bob")
except BaseException as exc:
# HOW DO I CATCH THE FIRST OF THE FOLLOWING
# exceptions from outside of this, current,
# except clause?
raise ValueError("what is this madness?")
class AnythingYouCanThinkOf(Exception):
pass
raise AnythingYouCanThinkOf
out = "definitely not `hello world`"
finally:
print(out)
The above results in unhandled exception ValueError: what is this madness? before, we got No error!!! wowza!

Catch exception gets UnboundLocalError

I wrote a crawler to fetch information out of an Q&A website. Since not all the fields are presented in a page all the time, I used multiple try-excepts to handle the situation.
def answerContentExtractor( loginSession, questionLinkQueue , answerContentList) :
while True:
URL = questionLinkQueue.get()
try:
response = loginSession.get(URL,timeout = MAX_WAIT_TIME)
raw_data = response.text
#These fields must exist, or something went wrong...
questionId = re.findall(REGEX,raw_data)[0]
answerId = re.findall(REGEX,raw_data)[0]
title = re.findall(REGEX,raw_data)[0]
except requests.exceptions.Timeout ,IndexError:
print >> sys.stderr, URL + " extraction error..."
questionLinkQueue.task_done()
continue
try:
questionInfo = re.findall(REGEX,raw_data)[0]
except IndexError:
questionInfo = ""
try:
answerContent = re.findall(REGEX,raw_data)[0]
except IndexError:
answerContent = ""
result = {
'questionId' : questionId,
'answerId' : answerId,
'title' : title,
'questionInfo' : questionInfo,
'answerContent': answerContent
}
answerContentList.append(result)
questionLinkQueue.task_done()
And this code, sometimes, may or may not, gives the following exception during runtime:
UnboundLocalError: local variable 'IndexError' referenced before assignment
The line number indicates the error occurs at the second except IndexError:
Thanks everyone for your suggestions, Would love to give the marks that you deserve, too bad I can only mark one as the correct answer...
In Python 2.x, the line
except requests.exceptions.Timeout, IndexError:
is equivalent to
except requests.exceptions.Timeout as IndexError:
Thus, the exception caught by requests.exceptions.Timeout is assigned to IndexError. A simpler example:
try:
true
except NameError, IndexError:
print IndexError
#name 'true' is not defined
To catch multiple exceptions, put the names in parentheses:
except (requests.exceptions.Timeout, IndexError):
Later, an UnboundLocalError can occur because the assignment to IndexError makes it a local variable (shadowing the builtin name):
>>> 'IndexError' in answerContentExtractor.func_code.co_varnames
True
So, if requests.exceptions.Timeout was not raised, IndexError will not have been (incorrectly) defined when the code attempts except IndexError:.
Again, a simpler example:
def func():
try:
func # defined, so the except block doesn't run,
except NameError, IndexError: # so the local `IndexError` isn't assigned
pass
try:
[][1]
except IndexError:
pass
func()
#UnboundLocalError: local variable 'IndexError' referenced before assignment
In 3.x, the problem will occur (after fixing the except syntax, which makes the error more obvious) even if the first exception is caught. This is because the local name IndexError will then be explicitly deld after the first try/except block.
When you say
except requests.exceptions.Timeout ,IndexError:
Python will except requests.exceptions.Timeout error and the error object will be IndexError. It should have been something like this
except (requests.exceptions.Timeout ,IndexError) as e:
except requests.exceptions.Timeout ,IndexError:
means same as except requests.exceptions.Timeout as IndexError
You should use
except (requests.exceptions.Timeout, IndexError):
instead

nested try/except in Python

try:
commands
try:
commands
try:
commands
try:
commands
except:
commands
return to final commands
except:
commands
return to final commands
except:
commands
return to final commands
except:
commands
final commands
Which instruction have I to write in place of return to final commands to make that any except returns to the top-level instructions following the outer try? And is it an acceptable structure?
Edit: Here is a toy example (I know I can do it using ifs, it's only an example; suppose you have to write it using try/except).
# calculate arcsin(log(sqrt(x)-4))
x = choose one yourself
try
x1=sqrt(x)
return to final message
try
x1=log(x1-4)
return to final message
try
x2=arcsin(x1)
return to final message
except
message="Impossible to calculate arcsin: maybe an argument outside [-1,+1]?"
except
message="Impossible to calculate logarithm: maybe a not positive argument?"
except
message="impossible to calculate square root: maybe a negative argument?"
final message:
print message
At the very least you should be able to reduce this structure to only 2 nested levels by reraising the exception to avoid the rest of the block:
# calculate arcsin(log(sqrt(x)-4))
x = ?
message = None
try:
try:
x1 = sqrt(x)
except Exception:
message = "can't take sqrt"
raise
try:
x1 = log(x1-4)
except Exception:
message = "can't compute log"
raise
try:
x2 = arcsin(x1)
except Exception:
message = "Can't calculate arcsin"
raise
except Exception:
print message
Really, this is not the way to do it, at least in this example. The problem is that you are trying to use exceptions like return error codes. What you should be doing is putting the error message into the exception. Also, normally the outer try/except would be in a higher level function:
def func():
try:
y = calculate_asin_log_sqrt(x)
# stuff that depends on y goes here
except MyError as e:
print e.message
# Stuff that happens whether or not the calculation fails goes here
def calculate_asin_log_sqrt(x):
try:
x1 = sqrt(x)
except Exception:
raise MyError("Can't calculate sqrt")
try:
x1 = log(x1-4)
except Exception:
raise MyError("Can't calculate log")
try:
x2 = arcsin(x1)
except Exception:
raise MyError("Can't calculate arcsin")
return x2

What does except really do in Python?

I'm really new in Python and a have no experience with exceptions but I've read all the documentation and couldn't find an answer ... so I'm looking for a deeper view in except's semantics.
When we have for example:
try:
x = 2
except GreaterThanOne:
print("The value is greater than one")
In this case I want the message to be printed.Is there a way for the GreaterThanOne class(exception) to be defined to raise when the entered value is greater than one ?
Ok, let me be more specific ...
Every error raises by a specific rule which should be add in the error attributes, am I right ?
For example:
try:
myvalue = x / y
except ZeroDivisionError:
print("Some error message printed ...")
So when I use this code and enter for y to be 0 the exception ZeroDivisionError will raise ... Can I for example redefine ZeroDivisionError to raise like this but if y is set to be ... 2 or 3 or any other value ?
Input:
x = 10
y = 2
try:
myvalue = x / y
except ZeroDivisionError:
print("division by 2")
Output: division by 2
Here's an example that should help you understand. Run this in your Python interpreter and watch how the exception is raised and caught (or not caught) when you call set_val(2).
# Defining our Exception subclass:
class GreaterThanOne(Exception):
pass
# The global value we pretend to care about:
val = 0
# Function to set a value but possibly raise our new Exception
def set_val(new_val):
if new_val > 1:
raise GreaterThanOne("%d > 1" % new_val)
val = new_val
# Catching exception:
try:
set_val(0)
set_val(1)
set_val(2)
except GreaterThanOne:
print "Whoops - one of those values was greater than one"
# Not catching exception:
set_val(0)
set_val(1)
set_val(2)
set_val(3)
an try-except block catches exception in this block.
try:
#some stuff here
except ExceptionClass as e:
#Exception handling here
the class after the except keyword indicates which kind of exception you want to catch. Usually you give a specific class, like ValueError or KeyError. You can also use the Exception class, to catch any exception. Because all the other exceptionclasses inhert from Exception.
so if you want to use this construct, an exception needs to be raised, Either by a function / method you call, or you raise it yourself with the raise keyword.
like this:
try:
raise KeyError('Just for test')
except KeyError as e:
#Exception handling here
The try except doesn't automagically inspect the whole code between it, it just looks for exceptions... Or to be more specific, it looks for those exceptions you tell it to look for.
Of course you can also inspect the exception instance.
try:
raise KeyError('Just for test')
except KeyError as e:
print e.args
For more information, please see:
http://docs.python.org/2/tutorial/errors.html

Exception returning no exception

I got a code something like this:
try:
do_something()
except (urllib2.URLError, socket.timeout), er:
print something
except Exception, ex:
print "The code failed because", ex, "Please review"
Now, the problem is on executing the above code I am getting following output:
The code failed because Please review
p.s.: The 'ex' should return the name of the exception but its not returning anything. Any idea why?
In reference to #Yuji and #Peter, I tried this code:
try:
try:
print x
except Exception, ex:
print "ex:", ex
raise
except Exception, er:
print "er:", er
And the Output was:
ex: name 'x' is not defined .
er: name 'x' is not defined .
Now, why raise(er) is returning an error? And why it does not in you cases?
Not necessarily - the expectation is not entirely true. The following code prints nothing:
try:
raise BaseException()
except BaseException, ex:
print ex
But this prints "abc":
try:
raise BaseException("abc")
except BaseException, ex:
print ex

Categories

Resources