Python3 Errors and Exceptions
As a Python beginner, when you first learn Python programming, you often see some error messages. We haven't mentioned them before; this chapter will specifically introduce them.
Python has two kinds of errors that are easy to recognize: syntax errors and exceptions.
Python assert (assertion) is used to evaluate an expression, and triggers an exception when the expression condition is false.

Syntax Errors
Python syntax errors, also called parsing errors, are often encountered by beginners, as in the following example:
File "<stdin>", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
In this example, the function print() is detected to have an error: it is missing a colon before it.: 。
The syntax parser points out the line with the error and marks a small arrow at the position where the error was first found.
Exceptions
Even if the syntax of a Python program is correct, errors may still occur when running it. Errors detected during runtime are called exceptions.
Most exceptions are not handled by the program, and appear here in the form of error messages:
Example
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam is not defined, triggers an exception
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2 # int cannot be added to str, triggers an exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
Exceptions appear in different types, and these types are all printed as part of the information: the types in the example are ZeroDivisionError, NameError, and TypeError.
The front part of the error message shows the context in which the exception occurred, and displays specific information in the form of a call stack.
Exception Handling
try/except
Exceptions can be caught using thetry/exceptstatement.

In the following example, the user is asked to enter a valid integer, but the user is allowed to interrupt the program (using Control-C or a method provided by the operating system). The user's interruption will raise a KeyboardInterrupt exception.
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("You did not enter a number, please try again!")
The try statement works as follows:
First, the try clause is executed (the statements between the keyword try and the keyword except).
If no exception occurs, the except clause is ignored, and the try clause ends after execution.
If an exception occurs during the execution of the try clause, the rest of the try clause is ignored. If the type of the exception matches the name after except, then the corresponding except clause will be executed.
If an exception does not match any except, then this exception will be passed to an outer try.
A try statement may contain multiple except clauses to handle different specific exceptions respectively. At most one branch will be executed.
The handler will only handle exceptions in the corresponding try clause, not exceptions in handlers of other try statements.
An except clause can handle multiple exceptions at the same time; these exceptions are put in parentheses to become a tuple, for example:
pass
The last except clause can omit the exception name, and it will be used as a wildcard. You can use this method to print an error message and then raise the exception again.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
try/except...else
try/exceptThe statement also has an optionalelseclause. If this clause is used, it must be placed after all except clauses.
The else clause will be executed when no exception occurs in the try clause.

The following example checks in a try statement whether the file can be opened. If the file opens normally without an exception, the else part is executed to read the file content:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
Using the else clause is better than putting all statements in the try clause, because it avoids some unexpected exceptions that except cannot catch.
Exception handling not only handles exceptions that occur directly in the try clause, but also exceptions raised in functions called in the clause (even indirectly called functions). For example:
x = 1/0
>>> try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero
try-finally Statement
The try-finally statement executes the final code regardless of whether an exception occurs.

In the following example, the finally statement executes regardless of whether an exception occurs:
Example
example()
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
finally:
print('This sentence will be executed regardless of whether an exception occurs.')
Raising Exceptions
Python uses the raise statement to raise a specified exception.
The raise syntax format is as follows:
raise [Exception [, args [, traceback]]]

The following example raises an exception if x is greater than 5:
if x > 5:
raise Exception('x cannot be greater than 5. The value of x is: {}'.format(x))
Executing the above code will raise an exception:
Traceback (most recent call last):
File "test.py", line 3, in <module>
raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 5。x 的值为: 10
The only parameter of raise specifies the exception to be raised. It must be an instance of an exception or an exception class (that is, a subclass of Exception).
If you only want to know whether an exception was raised, and do not want to handle it, then a simple raise statement can raise it again.
raise NameError('HiThere') # Simulate an exception.
except NameError:
print('An exception flew by!')
raise
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere
User-defined Exceptions
You can have your own exceptions by creating a new exception class. The exception class inherits from the Exception class, either directly or indirectly, for example:
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
In this example, the default __init__() of the Exception class is overridden.
When a module can raise multiple different exceptions, a common practice is to create a base exception class for this package, and then create different subclasses for different error situations based on this base class:
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
Most exception names end with 'Error', just like standard exception naming.
Defining Clean-up Actions
The try statement has another optional clause that defines clean-up actions that are executed under all circumstances. For example:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
In the above example, regardless of whether an exception occurs in the try clause, the finally clause will be executed.
If an exception is raised in the try clause (or in the except and else clauses), and no except catches it, then this exception will be raised after the finally clause is executed.
The following is a more complex example (containing both except and finally clauses in the same try statement):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
Predefined Clean-up Actions
Some objects define standard clean-up behavior. Whether or not the system has used it successfully, once it is no longer needed, this standard clean-up behavior will be executed.
The following example demonstrates trying to open a file and then print the content to the screen:
print(line, end="")
The problem with the above code is that after execution, the file remains open and is not closed.
The with keyword statement can ensure that objects such as files will correctly execute their clean-up method after use:
for line in f:
print(line, end="")
After the above code is executed, even if a problem occurs during processing, the file f will always be closed.
For more content about the with keyword, refer to:Python with Keyword