Why exception (try-except Exception) does not work? - python

Here is the code. For some reason, if I have type_of_model, neitehr X, nor Y exception does not work. The exception does not appear.
`def preprocess_corresponds_to_model(type_of_model: str) -> function:
try:
if type_of_model == "X":
preprocessing_function = preprocess_location_df
return preprocessing_function
elif type_of_model == "Y":
preprocessing_function = preprocess_event_df
return preprocessing_function
except FileNotFoundError as exception:
raise Exception(
f"The model {type_of_model} does not exist."
"The model should be either X or Y"
) from exception`
I expect that when as an input parameter I have neither X, nor Y I will see an exception message and my python script will be interrupted. But nothing happens.

You do not open any files in the scope of the exception handler. You return a function which is called outside that scope. So the handler is ineffective.

Related

Test for proper exception with Pytest

I want to test if a Django Rest Framework returns the proper exception when required, but the test always fails when the exception is raised, instead of succeeding when the exception is the right one:
This is my view:
#api_view(http_method_names=['GET'])
def get_fibonacci(request: Request) -> Response:
"""
Calculates the fibonacci value for number sent as query_param 'n'
"""
try:
n = int(request.query_params['n'])
except ValueError:
raise ValueError("The value of 'n' must be an integer.")
fibonacci_of_n = fibonacci_dynamic_v2(n)
return Response(fibonacci_of_n)
And this is my test:
def test_n_is_a_string_returns_proper_exception(client) -> None:
test_url = f"{fibonacci_url}?n=str"
response = client.get(test_url)
assert response.status_code == 404
And this is the result of the test:
=============================== short test summary info =======================================
FAILED tests/test_api.py::test_n_is_a_string_returns_proper_exception - ValueError: The value of 'n' must be an integer.
Results (1.08s):
23 passed
1 failed
- api/coronavstech/fibonacci_methods/tests/test_api.py:20 test_n_is_a_string_returns_proper_exception
I don't know how to instruct Pytest to succeed the test when the exception is the right one, instead of failing it because there was an exception, which is the result expected from the request.
For catching the exception, you can use pytest.raises() like follows:
def test_n_is_a_string_returns_proper_exception(client) -> None:
test_url = f"{fibonacci_url}?n=str"
with pytest.raises(ValueError):
response = client.get(test_url)
You can even check the exception message:
def test_n_is_a_string_returns_proper_exception(client) -> None:
test_url = f"{fibonacci_url}?n=str"
with pytest.raises(ValueError, match="^The value of 'n' must be an integer\.$"):
response = client.get(test_url)
But the ValueError being thrown inside your view is probably not what you wanted, as it will be shown as a generic 500 error.

The type error does not print the exception statement that I included

The purpose here is to catch all the errors when a sequence is tested using checked_f(seq). I tested this program by running checked_f([]), checked_f([1,2,3]) etc. The program catches errors for every test and displays "carefree_f() raised a known exception" except for this test checked_f((1, 2), (2, 3)).It doesn't print this statement "carefree_f() raised a known exception".
def checked_f(seq):
try:
return carefree_f(seq)
except TypeError:
print('carefree_f() raised a known exception')
return None
except ZeroDivisionError:
print('carefree_f() raised a known exception')
return None
except IndexError:
print('enter code here carefree_f() raised a known exception')
return None
except AttributeError:
print('carefree_f() raised a known exception')
return None
def carefree_f(seq):
(u, v) = seq.pop()
while seq:
(x, y) = seq.pop()
u += x
v += y
return u / v
except for this test checked_f((1, 2), (2, 3))
In this case, the error is in the caller.
checked_f() is defined to accept one argument, but you're passing it two arguments: (1,2), (2,3).
Therefore the call is invalid, checked_f() is not actually called, and the calling code raises an exception.

How to continue looping after a module defined exception in Python?

I loop though a list of currencies in order to download price series from an API and it happens that some of them are not supported so that it raises a module defined exception class : ExchangeError: This currency pair is not supported.
When it occurs I would like to continue the loop to the next currency but for some reason I'm unable to handle the module exception.
Here is an example that works fine with a built-in exception :
f = [1,2,3,4,'A',5]
def foo(nb):
return nb /2
for i in f :
try:
print(foo(i))
except TypeError :
continue
As expected it returns :
0.5
1
1.5
2
2.5
But as soon as it is a module (or user defined) exception it throws an error saying the exception is not defined :
#retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
def apiFetchOHLC(obj, currency, timeframe, option):
ohlcv = obj().fetch_ohlcv(currency, timeframe, since = option)
return ohlc
for c in currencies_list :
...
try :
# Download data
ohlc = apiFetchOHLC(obj, c, tf, maxCandlesLimit)
# except : # works fine
except ExchangeError : # doesn't work
print("Oops! That was no valid currency. Continue...")
continue
This is the error I get when I run the loop :
except ExchangeError:
NameError: name 'ExchangeError' is not defined
To make it works I need to remove the exception type ExchangeError but to me it is not a workaround because it will continue the loop whatever the exception is, and sometimes I need to retry the download.
How can I achieve this with try and except or with the retrying package ? (link)
def foo(count):
try:
while(count < 10):
if(count%2 == 1):
raise Exception()
print(count)
count = count+1
except:
print( str(count) + ' -> Exception')
foo(count+1)
foo(2)
Whenever an exception occurs in a try block, handle it in except block as follows -
To continue the process you are doing in try block, you should reach the try block from an except block - keep the try block in a function, name it foo, so that you could call it from the except block
To continue from the next iteration, you need to know the previous iteration where the exception has been raised - pass an argument to that function
After identifying the problem better I have found that I needed to give the full name space of the exception class I want to catch:
for c in currencies_list :
...
try :
# Download data
ohlc = apiFetchOHLC(obj, c, tf, maxCandlesLimit)
except ccxt.ExchangeError :
print("Oops! That was no valid currency. Continue...")
continue

Jump into the line instruction that caused an exception in python after the exception is called

Is there any way to return back and repeat the instruction that was handling an exception in Python?
E.g. if we get some data by input() method, and for some reason is caused an exception (e.g. when trying to convert the input string into int), we raised the exception, but after the exception, I would like again to go to the same line where the input() is.
Just note, "continue" is not an option, even if it is in a loop, because it could be several different input() assigning them to a different variables in different parts of the loop.
So the question again is:
while 1:
try:
foo = int(input(">")
...some other code here...
bar = int(input(">")
...some other code here...
fred = int(input(">")
...some other code here...
except Exception:
... do something for error handling and ...
jump_back_and_repeat_last_line_that_caused_the_exception
Imagine that the above code could be in a loop, and the exception can be caused in any instruction (foo... bar... fred...etc, or even can be any other line). So, if it fails in the "bar" line, it should try again the "bar" line.
Is there any reserved word to do this in python?
Define a function; Handle exception there.
def read_int():
while 1:
try:
value = int(input('>'))
except ValueError:
# Error handling + Jump back to input line.
continue
else:
return value
while 1:
foo = read_int()
bar = read_int()
fred = read_int()
There might be a way to do that, but it will probably result with a very poor design.
If I understand you correctly, then your problem is with the exception caused by calling input.
If that is indeed the case, then you should simply implement it in a separate method, which will handle the exception properly:
foo = getUserInput()
...some other code here...
bar = getUserInput()
...some other code here...
fred = getUserInput()
...some other code here...
def getUserInput():
while 1:
try:
return int(input(">"))
except Exception:
pass
don't do nothing in except:
while 1:
try:
a=int(raw_input('input an integer: ')) #on python2 it's "raw_input" instead of "input"
break
except ValueError, err:
# print err
pass
print 'user input is:', a
output is:
D:\U\ZJ\Desktop> py a.py
input an integer: a
input an integer: b
input an integer: c
input an integer: 123
user input is: 123

Wrapping exceptions in Python

I'm working on a mail-sending library, and I want to be able to catch exceptions produced by the senders (SMTP, Google AppEngine, etc.) and wrap them in easily catchable exceptions specific to my library (ConnectionError, MessageSendError, etc.), with the original traceback intact so it can be debugged. What is the best way to do this in Python 2?
The simplest way would be to reraise with the old trace object. The following example shows this:
import sys
def a():
def b():
raise AssertionError("1")
b()
try:
a()
except AssertionError: # some specific exception you want to wrap
trace = sys.exc_info()[2]
raise Exception("error description"), None, trace
Check the documentation of the raise statement for details of the three parameters. My example would print:
Traceback (most recent call last):
File "C:\...\test.py", line 9, in <module>
a()
File "C:\...\test.py", line 6, in a
b()
File "C:\...\test.py", line 5, in b
raise AssertionError("1")
Exception: error description
For completeness, in Python 3 you'd use the raise MyException(...) from e syntax.
This answer is probably a little bit late, but you can wrap the function in a python decorator.
Here is a simple cheatsheet on how different decorators.
Here is some sample code of how to do this. Just change the decorator to catch different errors in the different ways that you need.
def decorator(wrapped_function):
def _wrapper(*args, **kwargs):
try:
# do something before the function call
result = wrapped_function(*args, **kwargs)
# do something after the function call
except TypeError:
print("TypeError")
except IndexError:
print("IndexError")
# return result
return _wrapper
#decorator
def type_error():
return 1 / 'a'
#decorator
def index_error():
return ['foo', 'bar'][5]
type_error()
index_error()
Use raise_from from the future.utils package.
Relevant example copied below:
from future.utils import raise_from
class FileDatabase:
def __init__(self, filename):
try:
self.file = open(filename)
except IOError as exc:
raise_from(DatabaseError('failed to open'), exc)
Within that package, raise_from is implemented as follows:
def raise_from(exc, cause):
"""
Equivalent to:
raise EXCEPTION from CAUSE
on Python 3. (See PEP 3134).
"""
# Is either arg an exception class (e.g. IndexError) rather than
# instance (e.g. IndexError('my message here')? If so, pass the
# name of the class undisturbed through to "raise ... from ...".
if isinstance(exc, type) and issubclass(exc, Exception):
e = exc()
# exc = exc.__name__
# execstr = "e = " + _repr_strip(exc) + "()"
# myglobals, mylocals = _get_caller_globals_and_locals()
# exec(execstr, myglobals, mylocals)
else:
e = exc
e.__suppress_context__ = False
if isinstance(cause, type) and issubclass(cause, Exception):
e.__cause__ = cause()
e.__suppress_context__ = True
elif cause is None:
e.__cause__ = None
e.__suppress_context__ = True
elif isinstance(cause, BaseException):
e.__cause__ = cause
e.__suppress_context__ = True
else:
raise TypeError("exception causes must derive from BaseException")
e.__context__ = sys.exc_info()[1]
raise e

Categories