New to Python, so I'm sure this is a noob question, but Googling isn't availing me of a clear answer.
Given the following function which is intended to ensure that the user input is a string, why can't I (or how can I) add a print statement when the exception is triggered? The print statement I've inserted there doesn't work.
def string_checker(action):
try:
check = isinstance(action, basestring)
if check == True:
return True
except ValueError:
print "We need a string here!"
return None
action = "words"
string_checker(action)
This may do what you want:
def string_checker(action):
try:
assert isinstance(action, basestring)
return True
except AssertionError:
print "We need a string here!"
return None
action = "words"
string_checker(action)
string_checker(21)
But you could also return "We need a string here!" instead of printing it, or return False, for consistency.
The problem is that you're never raising a value error if action isn't a string. Try this:
def string_checker(action):
try:
check = isinstance(action, basestring)
if check:
return True
else:
raise ValueError
except ValueError:
print "We need a string here!"
return None
But really, I don't think you need an exception. This should work fine:
def string_checker(action):
try:
check = isinstance(action, basestring)
if check:
return True
else:
print "We need a string here!"
return None
I'm not sure I understand. This appears to print "We need a string here!":
def string_checker(action):
try:
raise ValueError()
check = isinstance(action, basestring)
if check == True:
return True
except ValueError:
print "We need a string here!"
return None
action = "words"
string_checker(action)
raw_input('#')
Note the raise ValueError() in the try. Are you sure an exception is being thrown?
Related
The runtime keeps telling me:
expected an indented block
But I don't want write nothing inside my except block, I just want it to catch and swallow the exception.
Just write
pass
as in
try:
# Do something illegal.
...
except:
# Pretend nothing happened.
pass
EDIT: #swillden brings up a good point, viz., this is a terrible idea in general. You should, at the least, say
except TypeError, DivideByZeroError:
or whatever kinds of errors you want to handle. Otherwise you can mask bigger problems.
For those who are very unclear as to why you would want to do this. Here is an example where I initially thought that an empty block would be a good idea:
def set_debug_dir(self, debug_dir=None):
if debug_dir is None:
debug_dir = self.__debug_dir
elif isinstance(debug_dir, (Path, str)):
debug_dir = debug_dir # this is my null operation
elif isinstance(debug_dir, list):
debug_dir = functools.reduce(os.path.join, debug_dir)
else:
raise TypeError('Unexpected type for debug_dir: {}'.format(type(debug_dir).__name__))
But it would be more clear to reorganize the statement:
def set_debug_dir(self, debug_dir=None):
if debug_dir is None:
debug_dir = self.__debug_dir
elif isinstance(debug_dir, list):
debug_dir = functools.reduce(os.path.join, debug_dir)
elif not isinstance(debug_dir, (Path, str)):
raise TypeError('Unexpected type for debug_dir: {}'.format(type(debug_dir).__name__))
I've never done this in more permanent code, but I frequently do it as a placeholder
if some_expression:
True
else:
do_something(blah)
Just sticking a True in there will stop the error. Not sure if there's anything bad about this.
Hi I'm pretty new to Python and I've just started to learn about errors and exceptions.I have this function in a class that inserts a line at a given index called num.I know python will raise an error if no num is given but I want to raise my own error.How do I do that?This is what I tried. But the error raised is still the default error?
def insertNum(self, num, line):
if num== None:
raise Exception("Num not specified.")
else:
self.list.insert(num, line)
return self.list
You can use try...except statement.
def insertNum(num, line):
try:
list.insert(num, line)
return list
except:
print('custom error')
You can set the default value of num to None and then check if the value is None.
def insertNum(self, line, num=None):
if num is None:
raise Exception("Num not specified.")
else:
self.list.insert(num, line)
return self.list
If you pass only one parameter to the insertNum method, num will be set the None (the default value) and will raise the exception.
If you don't want to change the order of the arguments, you can use this:
def insertNum(self, num, line=None):
if line is None:
raise Exception("Num not specified.")
else:
self.list.insert(num, line)
return self.list
A simple demonstration for how default arguments work:
>>> def foo(bar, baz=None):
... print(bar, baz)
...
>>> foo(1, 2)
1 2
>>> foo(2)
2 None
I suggest you read about exceptions and errors
But the main idea is that you catch errors and then you handle them the way you like.
try:
#do something
except Exception as e:
# error occured
print("A wild error appeared")
wrap your function with another function that will have try and except` and there you could raise what ever error/exception you want.
def wrapper_func(self, num, line):
try:
self.insertNum(num, line)
except Exception as e:
raise Exception("whatever you want")
I was looking at this list of python quirks and was amused that this returns False:
def t():
try:
return True
finally:
return False
After seeing this I saw the answers here and here which presented the reason why, and that's that the finally clause will always be executed, no exceptions.
My question is, where is the previous return value stored:
def t():
try:
return True
finally:
...
Why doesn't this return None but instead returns the original True?
And is it possible to access the going to be returned value programatically?
def t():
try:
return True
finally:
...
# if returning != None: return False
I'd like to know if it's possible to do this without using a variable for example:
def t():
retval = None
try:
retval = "Set"
finally:
if retval != None:
return retval
else:
return "Not Set"
and
def t():
retval = None
try:
...
finally:
if retval != None:
return retval
else:
return "Not Set"
return 'Set' and 'Not Set' respectively.
Why doesn't this return None but instead returns the original True?
From the docs:
The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement.
So this means that if a return statement is present in the finally clause that value will be returned (since the finally block is guaranteed to execute fully, any return statement inside it will be executed as well). Otherwise, if the try/except block was going to return a value, that value is returned.
This means that
def t():
try:
print("Inside try")
return "Return from try"
finally:
print("Inside finally")
return "Return from finally"
Will execute exactly as:
def t():
try:
print("Inside try")
# start of old finally block, executed "on the way out"
print("Inside finally")
return "Return from finally"
# end of old finally block, inserted right before return statement in try
return "Return from try"
finally:
pass
And is it possible to access the going to be returned value programatically?
No, you can't access the value after the return statement in other parts of the code without saving it.
What's the best way to handle a case where a function returns None. For example:
def my_function():
if <some_stuff_works>:
return <stuff>
else:
return None
my_var = my_function()
What I'd like to do is raise an exception if my_var is None and then set to a certain value. So something like:
try:
my_var = my_function()
except ValueIsEmpty:
my_var = "EMPTY"
Does that make sense?
If you can't modify the function, there's no need to come up with a creative exception: just check if it is None and give it an appropriate value.
my_var = my_function()
if my_var is None:
my_var = 'default_value'
Since you're want to use exceptions, try this;
def my_function():
if <some_stuff_works>:
return <stuff>
raise ValueError
try:
my_var = my_function()
except ValueError:
my_var = "EMPTY"
You can do this:
var = my_function() or 'default_value'
But, var will be equal to 'default_value' when my_function returns
None (what you want)
False
0
empty list [] (thanks to #roganjosh)
Up to you to choose what you want. If you don't what this, #brianpck's answer's still the best one.
You also make the function raise an exception instead of returning None.
def my_function():
if <some_stuff_works>:
return <stuff>
else:
raise SomeException # maybe TypeError, whatever
And then call it like this:
try:
result = my_function()
except SomeException:
result = 'EMPTY'
Or even better:
def my_function():
if <some_stuff_works>:
return <stuff>
# no need for the else because return end up the function execution.
# so if it returns <stuff>, it will stop, and not look further
return 'EMPTY'
I have a question about unittest.
How to make a test to see if is there an exception?
an example:
Datum(3,32,2012)
If i call class Datum like this, where month is not in range (>31), it's everything OK, it throws an Exception and thats OK. But I want to make an unittest if Exception is OK, if is catching an exception ok..?
I made some test but and these were only with True values, and they are ok. I have no idea how to test in this way.. and search on internet..
thanks for reply.
import date,datetime
class Datum():
def __init__(self,day,month,year):
try:
d=int(day)
dvm=stevilodnivmesecu(month,year)
if (d>=1 and d<=dvm):
self.d=d
else:
raise Exception("Day out of moth range")
except:
raise ValueError("Day is not a number")
try:
m=int(month)
if m>=1 and m<=12:
self.m=m
else:
raise Exception("Month out of range")
except:
raise ValueError("Month is not a number")
try:
l=int(year)
if l>=1000 and l<=9999:
self.l=l
else:
raise Exception("Year is out of range")
except:
raise ValueError("Year is not a number")
def __repr__(self):
return repr(self.d)+"."+repr(self.m)+"."+repr(self.l)
def monthrange(month,year):
if month==2:
if jeprestopno(year)==True:
return 29
elif jeprestopno(year)==False:
return 28
elif month>=1 and month<=7:
if month%2!=0:
return 31
elif month>7 and month<=12:
if month%2==0:
return 31
elif month>=1 and month<=7:
if month%2==0:
return 30
elif month>7 and month<=12:
if month%2!=0:
return 30
else:
pass
def oneplusyear(year):
if year%4==0 or (year!=100 and year%4==0) or (year%400==0 and year%100==0):
return True
else:
return False
Use
self.assertRaises(ValueError,Datum,3,32,2012)
in your unittest.TestCase test to assert that Datum(3,32,2012) raises a ValueError.
Reference:
Documentation on the various types of asserts you can make in
TestCases.