If I have an expression of 1/0
, obviously, it gets error:
try:
1/0
except ZeroDivisionError as err:
print(err) # this prints: division by zero
And the second try, replacing 1/0
by raise ZeroDivisionError
...
try:
raise ZeroDivisionError
except ZeroDivisionError as err:
print(err) # this prints: (nothing)
It prints nothing. Isn't an exception came from raise
, same as the a general expression?
Also, how to understand this difference more clearly?
All exceptions are a subclass of BaseException
, therefore all built-in exceptions should have an args
attribute.
args
:The tuple of arguments given to the exception constructor. Some built-in exceptions (like
OSError
) expect a certain number of arguments and assign a special meaning to the elements of this tuple, while others are usually called only with a single string giving an error message.
The args
tuple or string can be provided as the first argument when you raise the exception.
try:
raise ZeroDivisionError("error")
except ZeroDivisionError as err:
print(err) # prints "error"
The err
from except Exception as err:
is the Exception instance, when you print(err)
, you're actually calling the __str__
method of the Exception. Most Exception class's __str__
return's args
, since it's the default behaviour of BaseException; __str__
will return otherwise if the exception class override BaseException's __str__
.
When you raised a plain ZeroDivisionError
, you provided no args
, and ZeroDivisionError
does not have a custom __str__
method, therefore it printed args
by default, a.k.a args = None
.
As for your question:
Isn't an exception came from
raise
, same as the a general expression?
Yes. They are the same.
try:
raise ZeroDivisionError("division by zero")
except ZeroDivisionError as err:
print(err)
This will output the same as 1/0
.
I went ahead and dig through the source code. //
(integer division) and /
(true division) have a slightly different error message. But basically they are defined as such:
if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"division by zero");
return -1;
}
Whereas size_b
is the divisor. As you can see, 1/0
or any division by zero raises a ZeroDivsionError
with args
set as "division by zero"
or "integer division or modulo by zero"
depending how you divide.