Try + Except only catches certain exceptions - python

TL;DR: Why are my exceptions triggering only in certain situations, despite the fact that it is the same error?
The code successfully catches a NameError with an all numerical argument. So if someone mistakenly inputs a number instead of an operator, it gives them the correct exception error message. However, my code fails to catch other exceptions, and I'm unsure why.
For example:
print(better_calc(5, 5, 5))
This returns the desired exception message of
5 5 5 = Error: Name error. Please check your input
However, it does not catch other errors. Instead, it terminates the programme.
For example,
print(better_calc(5, g, 5))
This returns ''NameError: name 'g' is not defined'', without triggering the exception or the exception message.
Similarly
print(better_calc(5, *, 5))
This returns ''SyntaxError: invalid syntax'', without triggering the exception or the exception message.
I realize that if I included quotation marks on the operator, that the code would work, however, my goal is to trigger the exceptions.
def better_calc(num1, op, num2):
try:
if op == "+":
result = num1+num2
elif op == "-":
result = num1-num2
elif op == "*":
result = num1*num2
elif op == "/":
num1/num2
except NameError:
print(f"Error: Name error. Please check your input")
except UnboundLocalError:
print(f"Error: Value error. Please check your input")
except SyntaxError:
print(f"Error: Syntax Error. Please check your input")
print(num1, op, num2, "=")
return result
print(better_calc(5, 5, 5))

Just to consolidate the answers already given in the comments, try/except blocks can only handle errors that are raised between the try: and the first except block.
try:
# raised exceptions in this block can be caught
foo = "bar"
except FooError:
# catches a raised FooError but any exceptions raised here are
# outside of the try block and will not be handled. Another try/except
# block could be added here to catch these exceptions
pass
except Exception as e:
# a trick to log exceptions but then let the exception run
print(e)
raise
The call to the function print(better_calc(5, g, 5)) is outside of the function's try block and will not be caught.
And syntax errors like print(better_calc(5, *, 5)) keep the program from even running, which is definitely outside of the function's try block.

Related

How to continue with the execution even if i catch an error [duplicate]

This question already has answers here:
Catch exception and continue try block in Python
(12 answers)
Closed 11 months ago.
I want to control the error just printing it but continuing with the rest, por example:
try:
list =('a',2,3,5,6,'b',8)
print(list[8])
print("continue execution")
except:
print("An exception occurred")
It just will print the error but not the continue execution, is possible to continue even after exception?
What is missing and you're looking for is the finally instruction.
Syntax:
try:
#search for errors
except:
#if errors found, run this code
finally:
#run this code no matter if errors found or not, after the except block
The finally block contains the code that will be run after the except block, no matter if errors were raised or not.
See if this rearrangement of your own code helps:
list =('a',2,3,5,6,'b',8)
try:
print(list[8])
except:
print("An exception occurred")
print("continue execution")
If it matters for you to "print continue" right after exception occurrence , then you can put whatever you want to do before exception in a "bool function" and then inside the "try" check if function succeed or not.it means "if error occurred continue ,else show "An exception occurred".
try:
assert doStuff() == False
print("continue execution")
except:
print("An exception occurred")

If for Exception

I am teaching myself python and I am still an amateur at remembering all the keywords.
So; simple question, is there to way to use an if statement for an exception?
I can make the exception(NameError) print something. However, I want to use an if statement for if the exception is executed, then do this.
Help would be greatly appreciated!
try-except blocks were designed specifically for the purpose of catching exceptions. if statements are conditionals and are not designed to work with exceptions.
Here's a simple program to demonstrate exception handling:
class SomeException(Exception):
pass
try:
print("In try block.")
raise SomeException()
except SomeException:
print("In except block.")
Additionally, if you need information about the exception, you can use a special except block:
class SomeException(Exception):
pass
try:
print("In try block.")
raise SomeException()
except SomeException as exc: #exc is the exception object
print("In except block.")
When creating exceptions, you can optionally pass one or more arguments to indicate why the exception was raised:
class SomeException(Exception):
pass
try:
print("In try block.")
raise SomeException("message")
except SomeException as exc:
print(exc.args[0]) #Prints "message"
Here's a tutorial on exceptions that I found particularly useful.
A "try-except" block is exactly what you're looking for. Any code in the "try" part is executed normally, but if there's an exception, instead of returning back, it goes to the "except" block.
To phrase it how you were asking, any code in an "except" block runs IF the specific exception was raised/excecuted.
Instead of an error like this:
print(x)
NameError: name 'x' is not defined
You could do this:
try:
print(x)
except NameError:
print("error!")
error!
It will print "error!" IF anything in the try: block resulted in a NameError.
You can also use "else" and "finally" for more control.
Any code in the Else block runs if there were no errors.
try:
print("Hello")
except:
print("Something went wrong")
else:
print("Nothing went wrong")
Hello
Nothing went wrong
Anything in a "finally" block runs after regardless of if there was an error or not.
try:
print(x)
except:
print("Something went wrong")
finally:
print("The 'try except' is finished")
Something went wrong
The 'try except' is finished
I recommend reading the W3 Schools page on Try Except.
https://www.w3schools.com/python/python_try_except.asp
Protip: you can do something like except Exception as e which will save info about the exception to e.

Python nested error handling

I want to ignore some exception in an library code (not my code)
as so:
try:
try: # not my code start
assert False
except:
print('not my code') # not my code end
except:
print('my code')
pass
So I will get into printing 'my code' at the end.
The results currently is:
'not my code' only.
You will get my code if the inner block, as a whole raises an exception. In your case, the inner block
try: # not my code start
assert False
except:
print('not my code') # not my code end
has handled it's exception, so, from the point of view of the outer try, it has completed successfully.
You could only cause the outer exception to be triggered by, raising an unhandled exception in the first try, or calling a function that raises an exception.

Is there any difference between return and raise an Exception?

Consider the following code:
def f(x):
if x < 10:
return Exception("error")
else:
raise Exception("error2")
if __name__ == "__main__":
try:
f(5) # f(20)
except Exception:
print str(Exception)
Is there any difference?
When should I use return Exception and When should I use raise?
raise and return are two inherently different keywords.
raise, commonly known as throw in other languages, produces an error in the current level of the call-stack. You can catch a raised error by covering the area where the error might be raised in a try and handling that error in an except.
try:
if something_bad:
raise generate_exception()
except CertainException, e:
do_something_to_handle_exception(e)
return on the other hand, returns a value to where the function was called from, so returning an exception usually is not the functionality you are looking for in a situation like this, since the exception itself is not the thing triggering the except it is instead the raiseing of the exception that triggers it.

Python - Try/Except, what is ok and what is wrong?

I have to deal with a large quantity of try/except. I'm in doubt about the right way of doing it.
Option 1:
inst = Some(param1, param2)
try:
is_valid = retry_func(partial(inst.some_other), max_retry=1)
except RetryException, e:
SendMail.is_valid_problem(e)
if is_valid:
print "continue to write your code"
...
*** more code with try/except ***
...
Option 2:
inst = Some(param1, param2)
try:
is_valid = retry_func(partial(inst.some_other), max_retry=1)
if is_valid:
print "continue to write your code"
...
*** more code with try/except ***
...
except RetryException, e:
SendMail.is_valid_problem(e)
In the Option 1, even is the exception is raised, "is_valid" will be tested and I don't need that.
In the Option 2, is what I think is correct but the code will look like a "callback hell".
What option should I choose or what option is the correct one?
Keep your exception handling as close as possible to the code that raises the exception. You don't want to accidentally mask a different problem in code you thought would not raise the same exception.
There is a third option here, use the else: suite of the try statement:
inst = Some(param1, param2)
try:
is_valid = retry_func(partial(inst.some_other), max_retry=1)
except RetryException, e:
SendMail.is_valid_problem(e)
else:
if is_valid:
print "continue to write your code"
...
*** more code with try/except ***
...
The else: suite is only executed if there was no exception raised in the try suite.
From your conditions, condition 1 is better and you can use else instead of if is_valid
Here are some of Try Except:
Here is simple syntax of try....except...else blocks:
try:
You do your operations here;
......................
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......................
else:
If there is no exception then execute this block.
The except clause with multiple exceptions:
try:
You do your operations here;
......................
except(Exception1[, Exception2[,...ExceptionN]]]):
If there is any exception from the given exception list,
then execute this block.
......................
else:
If there is no exception then execute this block.
The try-finally clause:
try:
You do your operations here;
......................
Due to any exception, this may be skipped.
finally:
This would always be executed.
I think option 1 is better. The reason is that you should always put inside a try except only the code which you expect to throw the exception. Putting more code increase the risk of catching an unwanted exception.
Make sure that if an Error will occur, keep the cause inside the try statement. That way, it will catch the error and sort it out in the except section. There is also finally. If the try doesn't work, but the "except" error doesn't work, it will act out the "finally" statement. If there is no finally, the program will get stuck. This is a sample code with try and except:
import sys
import math
while True:
x=sys.stdin.readline()
x=float(x)
try:
x=math.sqrt(x)
y=int(x)
if x!=y:
print("Your number is not a square number.")
elif x==y:
print("Your number is a square number.")
except(ValueError):
print("Your number is negative.")
ValueError is the error you get from sqrt-ing a negative number.

Categories

Resources