I'm assuming that following code suppose to print ("CustomExceptionALL"), but that never happens if we raise CustomException1, CustomException2 or CustomException3 while CustomExceptionALL works. Why except CustomExceptionALL doesn't catch CustomException3?
class CustomException1(Exception):
pass
class CustomException2(Exception):
pass
class CustomException3(Exception):
pass
class CustomExceptionALL(CustomException1, CustomException2, CustomException3):
pass
try:
raise CustomException3
except CustomExceptionALL as e:
print("CustomExceptionALL")
except Exception as e:
print(e)
The use case is more the other way round: you raise the derived exception and then catch it using the parent class. For example:
class Brexit(Exception):
pass
class Covid(Exception):
pass
class DoubleWhammy(Brexit, Covid):
pass
try:
raise DoubleWhammy
except Brexit as e:
print("Brexit")
except Exception as e:
print(e)
Because you can only catch subclasses of the specified exception. In your case, these two are false:
isinstance(CustomException3(), CustomExceptionALL) # False
issubclass(CustomException3, CustomExceptionALL) # False
(Because you are trying to catch a CustomExceptionALL, but a CustomException3 is not a CustomExceptionALL, but the other way around)
You can instead use a tuple of classes:
CustomExceptionALL = (CustomException1, CustomException2, CustomException3)
isinstance(CustomException3(), CustomExceptionALL) # True
issubclass(CustomException3, CustomExceptionALL) # True
try:
raise CustomException3
except CustomExceptionALL as e:
print("CustomExceptionALL") # This prints
except Exception as e:
print(e)
Related
Is there any way to raise multiple exceptions in python? In the following example, only the first exception is raised.
l = [0]
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('zero division error') from e
try:
l[1]
except IndexError as e:
raise Exception('Index out of range') from e
Is there any other way?
Once an exception is raised and not catched, the execution of your program will stop. Hence, only one exception can be launched in such a simple script.
If you really want your program to raise multiple exceptions, you could however create a custom Exception representing multiple exceptions and launch it inside an except block. Example:
class ZeroDivAndIndexException(Exception):
"""Exception for Zero division and Index Out Of Bounds."""
I = [0]
try:
1 / I[0]
except ZeroDivisionError as e:
try:
I[1]
# Here you may raise Exception('zero division error')
except IndexError as e2:
raise ZeroDivAndIndexException()
Here my solution a bit long but seems to work :
class CustomError(Exception):
pass
l = [0]
exeps = []
try:
1 / 0
except ZeroDivisionError as e:
exeps.append(e)
try:
l[1]
except IndexError as e:
exeps.append(e)
if len(exeps)!=0:
[print(i.args[0]) for i in exeps]
raise CustomError("Multiple errors !!")
I tried to throw an exception with array data:
raise Exception([ValidateError.YEAR, row])
When I tried to catch it I get this error:
'Exception' object is not subscriptable
Code is:
except Exception as e:
#invalid
print(e[0])
To access the Exception arguments you passed as a list, you should use .args.
So, I believe you were looking for the following:
except Exception as e:
#valid
print(e.args[0][0])
As a side note, you can pass multiple arguments without them being in a list:
raise Exception(ValidateError.YEAR, row)
And then you need one index less:
except Exception as e:
#also valid
print(e.args[0])
You can subclass Exception and implement the __getitem__ function like so:
class MyException(Exception):
def __init__(self, l):
self.l = l
def __getitem__(self, key):
return self.l[key]
try:
raise MyException([1, 2, 3])
except MyException as e:
print(e[0])
running it:
python3 main.py
1
Say I have a block of exception statements:
try:
expression
except err1:
#process error
...
...
except err10:
#process error
and I want to call sys.exit(1) if ANY of the exceptions are raised. Do I have to call it manually in every single sub-block or is there a built in way to have a statement akin to:
...
except err10:
#process error
"if any of these exception were raised":
sys.exit(1)
One thing you could do is:
flag = False
try:
expression
flag = True
except err1:
#process error
...
...
except err10:
#process error
if not flag:
sys.exit(1) #exit program
If the flag is False, that means that you didn’t pass through the try loop, and so an error was raised.
In Python, there is an optional else block which is executed in case no exception is raised. You may use this to set a flag for you code and exit the code out of the try/except block as:
is_exception = True
try:
expression
except err1:
# ... something
except err10:
# ... something else
else:
# This will be executed if there is no exception
is_exception = False
if is_exception:
sys.exit(1)
raised = True
try:
expression
except err1:
# process error
raise
...
except err10:
# process error
raise
else:
# if no error was raised
raised = False
finally:
if raised:
raise SystemExit
Here's what I was talking about in my comment:
isok = False
try:
#try to do something
isok = True
except err1:
#do something besides raising an exception
except err5:
#do something besides raising an exception
if not isok:
raise SystemExit
I wrote a function that needs to do 3 checks and if one of the tests fails it should return an exception of type of LookupError, but it doesn't work.
(*verify_checksum is another function)
def check_datagram(datagram, src_comp, dst_app):
try:
src_comp==datagram[0:16]
except LookupError:
return "Mismatch in src_comp"
try:
dst_app==datagram[40:48]
except LookupError:
return "Mismatch in dst_app"
try:
verify_checksum(datagram)
except False:
return "Wrong checksum"
return True
For example:
Input:
check_datagram("1111000000001111000011111111000001010101101010101111111111111111000000001111111100000000","0000111100001111", "11110000")
Expected output:
"Mismatch in dst_app"
def check_datagram(datagram, src_comp, dst_app):
if src_comp != datagram[0:16]:
raise LookupError("Mismatch in src_comp")
if dst_app != datagram[40:48]:
raise LookupError("Mismatch in dst_app")
if not verify_checksum(datagram):
raise LookupError("Wrong checksum")
return True # redundant?
With construction from NPE's answer you should use try..except there where you'll use declared check_datagram() function.
#python3
try:
check_datagram(a,b,c)
except LookupError as e:
print(str(e))
That allow you to get message from raised error.
Will this work?
try:
try:
field.value = filter(field.value, fields=self.fields, form=self, field=field)
except TypeError:
field.value = filter(field.value)
except ValidationError, e:
field.errors += e.args
field.value = revert
valid = False
break
Namely, if that first line throws a ValidationError, will the second except catch it?
I would have written it un-nested, but the second filter statement can fail too! And I want to use the same ValidationError block to catch that as well.
I'd test it myself, but this code is so interwoven now it's difficult to trip it properly :)
As a side note, is it bad to rely on it catching the TypeError and passing in only one arg instead? i.e., deliberately omitting some arguments where they aren't needed?
If the filter statement in the inner try raises an exception, it will first get checked against the inner set of "except" statements and then if none of those catch it, it will be checked against the outer set of "except" statements.
You can convince yourself this is the case just by doing something simple like this (this will only print "Caught the value error"):
try:
try:
raise ValueError('1')
except TypeError:
print 'Caught the type error'
except ValueError:
print 'Caught the value error!'
As another example, this one should print "Caught the inner ValueError" only:
try:
try:
raise ValueError('1')
except TypeError:
pass
except ValueError:
print 'Caught the inner ValueError!'
except ValueError:
print 'Caught the outer value error!'
To compliment Brent's answer, and test the other case:
class ValidationError(Exception): pass
def f(a): raise ValidationError()
try:
try:
f()
except TypeError:
f(1)
except ValidationError:
print 'caught1'
try:
try:
f(1)
except TypeError:
print 'oops'
except ValidationError:
print 'caught2'
Which prints:
caught1
caught2