When I use the 'raise' statement I meet something that I can't understand:
I know that in
raise exclass(args)
args
may be a string or a tuple containing several items of information (e.g., an error code and a string explaining the code)
but when I code this:
try:
raise TypeError(float([]))
except TypeError as e:
print e
I get this:
float() argument must be a string or a number
But float([]) is neither a string nor a tuple, is it a correct way to raise an exception?
Also in this case:
try:
raise float([])
except TypeError as e:
print e
And I get the same result:
float() argument must be a string or a number
As I know, in the raise statement, the first argument should be a class, an instance or a string, but the code above can work successfully, why?
Please tell me how are the examples working, thanks a lot.
My English is not good, please just ignore the mistakes in grammar.
This error happens because a list [] is not a valid argument for float(), and it has nothing to do with the exception part.
To test capturing the extra information in an exception, you can simply pass the extra data to the exception, like this:
>>> try:
... raise TypeError('hello')
... except TypeError as e:
... print(e)
...
hello
You can also use the generic Exception class:
>>> try:
... raise Exception('hello')
... except Exception as e:
... print(e)
...
hello
You can catch that particular exception like this:
>>> try:
... float([])
... except TypeError:
... print('Okay')
...
Okay
Related
I am running a script in a loop for each element of a list. If some elements cause an error, how to print a list of error-causing elements in the end after all the elements are looped through?
For example:
f=["ABC","PQR","UVW","XYZ"]
for f in f:
try:
'blah blah'
except:
continue
# print("Error causing elements are " ..........
Before getting started
I changed variable f in the for each loop to element for not getting confused and also I wrote a foo function that throws an exception randomly.
Solution
You can add the error-causing elements to a list in the main loop like this: (you have access to the error-causing element in the except: block by variable element in each loop)
f=["ABC","PQR","UVW","XYZ"]
error_elements = []
def foo(element):
from random import randint
if randint(0, 1) > 0:
raise Exception()
for element in f:
try:
foo(element)
except:
error_elements.append(element)
print("Error causing elements are ", error_elements)
Another Option
Or if you throw the exception, there's another option that you can use and pass the error-causing element and anything else to the Exception function call and access them in except block by catching the Exception like except Exception as e
f=["ABC","PQR","UVW","XYZ"]
error_elements = []
def foo(element):
from random import randint
if randint(0, 1) > 0:
raise Exception('blah blah', element)
for element in f:
try:
foo(element)
except Exception as e:
# print('Error message is:', e.args[0])
error_elements.append(e.args[1])
print("Error causing elements are ", error_elements)
Matin's answer is good. However if you have a list containing the same element multiple times you might want to use a set instead to keep your error message shorter:
f=["ABC","PQR","UVW","XYZ"]
errors=set()
for f in f:
try:
'blah blah'
except:
errors.add(f)
continue
# print(f"Error causing elements are {errors}" ..........
Try this!
try:
'your code'
except Exception as e:
print(f'The error was " {e} "')
else:
print("No errors")
Tell me that if this works!
Currently my app is working with several external APIs, and those functions can raise some kind of error, and I would like to be aware of all kind of situations and don't crash my app. In the following piece of code you can see my function, using slack api (it's just an example, not real example), and you can see how I'm creating a space giving the name and the emails. That function can returns several errors, like APIerror, TypeError... etc etc
Also you can see, all the functions in that file, can raise some errors so it is using try and except and try to don't break our app. In the except part, I don't want to do anything special, just return the error or I don't know, raise an custom error. In the future would be cool if I can enqueue that task if something goes wrong.
slack_client.py
def create_space():
try:
slack_api.create.space(spaceName='space name', email=emails)
except (...):
...
def delete_space():
try:
slack_api.delete.space(spaceId=space_id)
except (...):
...
I would like to refactor the try and except part, because I don't want to copy and paste try and except during all my slack_client class, but in case the connection is down, or some parameter is wron, the "Slack" API will raise me an error.
I thought about create a class, to run each function inside try and catch, but it's a bit weird and I will loose the arguments part like "spaceName='space name'", which I think it's really cool and clear.
def execute_func(func, *args):
try:
func(args)
except (..):
...
So would like some help for this kind of situation, because handle external API is not always really easy... (at the moment working with 2 external APIs)
In a previous life I used VAX/VMS and still remember great pleasure at discoverting LIB$SIG_TO_RET which converted a signal to a return value. You can do exactly the same in not many lines of Python, along the lines you indicated
def execute_func(func, *args, **kwargs):
try:
result = func( *args, **kwargs)
return (True, result)
except Exception as exc:
return ( False, exc)
Usage
result = execute_func( func, a1, a2, ... k1=v1, k2=v2, ...)
if result[0]:
func_result = result[1] # if it's useful
...
else:
# it went wrong, deal with the exception
caught_exception = result[1]
print( caught_exception)
You can catch any exception that is thrown and capture it in a variable to log or raise. You could even raise your own custom exception. Something like this should work:
First create your exception:
class CustomSlackException(Exception):
pass
Then raise it when the API you called throws some exception:
try:
slack_api.create.space(spaceName='space name', email=emails)
except Exception as e:
print(e)
raise CustomSlackException("Custom error message!")
Now you can catch your exception and handle it as needed.
I was wondering if you could re-raise a (specific) caught exception and have it caught by a later (general) except in the same try-except. As an example, I want to do something with a specific IOError, but if its not the expected IOError then the exception should be handled like any other error. What I initially tried:
try:
raise IOError()
except IOError as ioerr:
if ioerr.errno == errno.ENOENT:
# do something with the expected err
else:
# continue with the try-except - should be handled like any other error
raise
except Exception as ex:
# general error handling code
However, this doesn't work: the raise re-raises the exception outside the context of the try-except.
What would be the pythonic way of writing this to get the desired exception 'fall-through' behaviour?
(I'm aware there was a proposed 'conditional except' that wasn't implemented, which could've solved this)
If you ultimately want it to catch everything, make it do that. Catch first, sieve later. ;)
try:
raise IOError()
except Exception as ex:
if isinstance(ex, IOError) and ex.errno == errno.ENOENT:
# do something with the expected err
# do the rest
I am not an expert in writing pythonically, but I think one obvious approach (if you know that you're expecting one particular kind of exception), would be to use nested exception handling:
try:
try:
raise IOError()
except IOError as ioerr:
if ioerr.errno == errno.ENOENT:
# do something with the expected err
else:
# pass this on to higher up exception handling
raise
except Exception as ex:
# general error handling code
I know in your comment that you didn't want nested else's -- I don't know if nested exception handling is as bad in your book, but at the very least you can avoid code duplication.
So, I'm working on the same here, and after reviewing the available solutions, I'm going to go with catching the parent exception, and then testing for specifics. In my case I'm working with the dns module.
try:
answer = self._resolver.query(name, 'NS')
except dns.exception.DNSException, e: #Superclass of exceptions tested for
if isinstance(e, dns.resolver.NXDOMAIN):
#Do Stuff
elif isinstance(e, dns.resolver.NoAnswer):
# Do other stuff
else:
# Do default stuff
I am basically trying to improve upon Python: try-except as an Expression? with a couple of features
Ability to pass in extra args and kwargs to the "try-except" question. This is because I have a success function which takes in a few parameters
Failure function if callable should be called with the exception argument so it gets a chance to handle it.
Here is a sample code with a test however I am not able to get the last line to work
def method2(exc_class = None):
if exc_class:
raise exc_class()
def method1():
return "Hello world"
def try_except(function, failure, exceptions = [], args = [], kwargs = {}):
"""
Run the given function with args and kwargs. If it throws one of the
exceptions in the list then either return failure or call failure function
"""
try:
return function(*args, **kwargs)
except exceptions or Exception as e:
return failure(e) if callable(failure) else failure
if __name__ == "__main__":
#Prints hello world
print try_except(method1, "Failure")
#Prints Failure great!!
print try_except(method2, "Failure", kwargs = {"exc_class" : ValueError})
# I expect below line to print "Failure" properly but it throws a ValueError
print try_except(method2, "Failure", kwargs = {"exc_class" : ValueError}, exceptions=[ValueError])
My question here is the except exceptions or Exception as e: line does not substitute the list of exceptions properly. I cannot do *exceptions as shown in the original question because I want to take in extra parameters for the function.
I am okay to change the try_except to some extent though.
Note: I have considered doing a catch all except Exception as e and then checking if the exception class in in the list and if it is not then rethrow it. However that won't work because when I rethrow the original stack trace is lost and I do not want to do that.
When catching several exception types with one except clause, you can't use just any iterable object; you must specifically use a tuple. You can still allow try_except to take any iterable as an argument by creating a tuple in the except clause itself.
try:
return function(*args, **kwargs)
except tuple(exceptions or (Exception,)) as e:
return failure(e) if callable(failure) else failure
From the docs:
For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if it is the class or a base class of the exception object, or a tuple containing an item compatible with the exception.
Suppose i have this code
if form.is_valid():
form.save()
Now suppose my form is valid i have exception that foregin key value is linked to more than one column so it will raise exception
Now i want to know is there any way to grab that exception value and pass to jquery via AJAX
Because form is valid so it comes inside the loop but its not able to go after form.save
So how can i program that if exception occurs it get passed to jquery like
if exception
return HttpResponse(exception)
I get this exception
MultipleObjectsReturned at
/manage/Source/create/ get() returned
more than one Account -- it returned
3! Lookup parameters were
{'account_number':
u'121121'}
What type of exception it is
MultipleObjectsReturned is the exception.
try:
#do something
except MultipleObjectsReturned:
return HttpResponse('MultipleObjectsReturned')
I wouldn't recommend using a bare try/except to catch all exceptions, as you won't know exactly what's wrong.