In my scripts I wanna cleanup my error Handling. What I read is that I need:
try:
do something
exept:
raise Error("give error")
finaly:
print("something else")
The problem I have is that I don't know how to handle an error in this way in my former written function.
How do I create a try statement with multiple conditions like the simple example below.
def varlist(var, length):
from numpy import array
if len(array(var)) > length:
return(False)
raise ValueError('list is to long only first ' + str(length) + ' paramerets will be used')
elif len(array(var)) < length:
return(False)
raise ValueError('list is to short ' + str(length) + ' is less than required')
else:
return(True)
So in general my question is: How to handle an if/ try statement with multiple outputs all baased on their value....
In this case I have two outputs but I have others with more values( sometimes strings)
I don't quite get your problem but here is a code using the try statement:
def varlist(var, length):
from numpy import array
try:
return True
except len(array(var)) > length :
return False
raise ValueError('#Your Error message 1')
except len(array(var)) < length :
return False
raise ValueError('#Your Error message 2')
If you meant how to return multiple values, just 'pack' them in a tuple like this:
returntuple = ('statement1', 'statement2', etc)
return returntuple
Then you can 'unpack' it like this:
returntuple[1]
will return 'statement2'
Like this you can return multiple values. You need to trick python, because it doesn't provide returning multiple values(, as far as I know!). But if you 'pack' your values in a tuple or a listeverything is fine!
If those two answers doesn't get your problem, I'm sorry I just don't get the question.
Sincerely, heureka
Related
I have below code block:
try:
if str(symbol.args[0]) != str(expr.args[0]):
print('true')
raise SyntaxError('====error')
except:
pass
Here I am trying to raise Syntax error if certain condition is true.I am testing this code block, I can see 'true' is getting printed which means condition is met but even after that also the code is not throwing syntax error.
I am trying to understand what is wrong in the above code.
You're putting pass in the except: block which is swallowing the exception. Either remove the code from the try-except block or change pass to raise
Above answer is pointing the issue, I just want to give some examples to help you better understand how try/except works:
# Just raise an exception (no try/except is needed)
if 1 != 2:
raise ValueError("Values do not match")
# Catch an exception and handle it
a = "1"
b = 2
try:
a += b
except TypeError:
print("Cannot add an int to a str")
# Catch an exception, do something about it and re-raise it
a = "1"
b = 2
try:
a += b
except TypeError:
print("Got to add an int to a str. I'm re-raising the exception")
raise
try/except can also be followed by else and finally, you can check more about these here: try-except-else-finally
Something about the interaction between pytest, str() and python Error types breaks full error testing where we want to confirm the EXACT TEXT returned by the error.
Example below:
def erroring_func(name, required_item_list):
# skip boring bit. Just throw an error.
raise KeyError(f'{name} is missing required item(s): {required_item_list')
def test_erroring_func():
with pytest.raises(KeyError) as err:
name = 'This dataframe'
required_item_list = ['a column']
_ = erroring_func(name, required_item_list)
assert str(err.value) == f"{name} is missing required item(s): {required_item_list}"
This looks sensible, but will return the error:
assert '"This dataframe is missing required item(s): [\'lat\']"' == "This dataframe is missing required item(s): ['lat']
Somehow, str(err.value) creates single backslashes in the output that are EXTREMELY difficult to recreate in an f-string (actually impossible) or to insert in a string once created.
You can completely solve by matching how KeyError alters text. This can be done with an f-string with single quotes and then double quotes f'"your text {here}"'
assert str(err.value) == f'"{name} is missing required item(s): {required_item_list}"'
(With thanks to Anthony Sotile)
An incomplete patch (missing the major value of verbose errors) is to test that a fixed substring exists in the returned error.
def test_erroring_func()
with pytest.raises(KeyError) as err:
name = 'This dataframe'
required_item_list = ['a column']
_ = erroring_func(name, required_item_list)
assert "is missing required item(s):" in str(err.value)
PS. Updating to more modern pytest syntax, a regex match can be defined as a arg in pytest.raises
def test_erroring_func():
with pytest.raises(KeyError, match="is missing required item(s):") as err:
name = 'This dataframe'
required_item_list = ['a column']
_ = erroring_func(name, required_item_list)
Take a look at the following:
def mutate(self, info, first_id, second_id):
try:
first = Model.objects.get(pk=first_id)
second = Model.objects.get(pk=second_id)
except Model.DoesNotExist:
return Exception('Object does not exist.')
else:
...
How can I return a custom error message depending on which of the ids actually does not exist? It's be nice to have something like:
{first_id} does not exist
I can't have two different except blocks because it's the same Model. What to do?
You can simply split up your query's in two statements:
def mutate(self, info, first_id, second_id):
try:
first = Model.objects.get(pk=first_id)
except Model.DoesNotExist:
raise Exception('Your first id {} Does not exist'.format(first_id))
try:
second = Model.objects.get(pk=second_id)
except Model.DoesNotExist:
raise Exception('Your second id {} Does not exist'.format(second_id))
...
PS: you need to raise exceptions. Not return them.
I'm trying to test a fuction that dependets a of multiple user inputs to return some value.
I've already looked for multiples unswers here but none was able to resolve my problem. I saw things with parametrize, mock and monkey patch but none helped. I think a lot is because I don't clearly understood the concepts behind what was being done and I couldn't adapt to my problem. I saw suggestion of using external file for this but I don't wont to depend on that. I'm trying with pytest and python 3.7.3
The function that I want to test is something like this
def function():
usr_input = input('please enter a number: ')
while True:
if int(usr_input) < 5:
usr_input = input('please, enter a value less then 5: ')
else:
break
return usr_input
I want to know how can I pass two input values to test the function when the inserted value is not valid. Example: Send value 6 and 2, make an assert expecting value 2 and pass the test. My others tests look like this:
def test_input(monkeypatch):
monkeypatch.setattr('builtins.input', lambda x: 6)
test = function()
assert test == 2
but, for this case, they loop. It's possible to do this only with parametrize or other simple code?
EDIT
I added a int() in my "if", as wim pointed in the accepted answer, just to prevent any confusion for future readers. I'm assuming the cast is possible.
Two problems here, you need to convert the input into a number otherwise the comparison will fail, comparing a string with a number: usr_input < 5. Note that the real input will never return a number, only a string.
Once you've cleared that up, you can monkeypatch input with a callable that can return different values when called:
def fake_input(the_prompt):
prompt_to_return_val = {
'please enter a number: ': '6',
'please, enter a value less then 5: ': '2',
}
val = prompt_to_return_val[the_prompt]
return val
def test_input(monkeypatch):
monkeypatch.setattr('builtins.input', fake_input)
test = function()
assert test == 2
If you install the plugin pytest-mock, you can do this more easily with the mock API:
def test_input(mocker):
mocker.patch('builtins.input', side_effect=["6", "2"])
test = function()
assert test == 2
Write a program which gets an input from the user by asking 'Give me an input:',and passes this string to 'silly_function' if the function returns without an error.simply print whatever it returned. However: if the function produces a ValueError,the program should instead print'I cannot use this value'; if the function produces a TypeError,the program should instead print 'Invalid input'
def silly_function(a):
a = input('Give me an input')
try:
sily_function(a)
except ValueError:
print('I cannot see this value')[enter image description here][1]
Let's try this together.
Code Analysis
def silly_function(a):
a = input('Give me an input')
this is fine, it will prompt the user for an input**
try:
silly_function(a)
Why do you need to call silly_function again ? I don't think that was the intended behavior ?
Also silly_function doesn't do anything that will terminate the recursion or generate an error , so this is bound to break.
except ValueError:
print('I cannot see this value')[enter image description here][1]
Suppose this is a typo, but see != useand you are only handling one error and not the other one.
Suggestion
Let's right in pseudocode a bit of help
def error_handling_function(a):
a = input('Give me an input')
try:
silly_function(a)
except #input error here:
#handle error here
except #input error here:
#handle error here
def silly_function(a):
#write code that can break and generate the two error you are looking for