Python introductory tutorial | Python errors and exceptions

Python3 errors and exceptions

As a Python beginner, when you first learn Python programming, you will often see some error messages. We have not mentioned them before, but we will introduce them specifically in this chapter.

There are two types of errors in Python that are easy to spot: syntax errors and exceptions.

Python assert is used to evaluate an expression and trigger an exception when the expression condition is false.
Insert image description here

Grammatical errors

Python syntax errors, or parsing errors, are often encountered by beginners, as shown in the following examples

>>> while True print('Hello world')
  File "<stdin>", line 1, in ?
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

In this example, the function print() is checked for an error because it is missing a colon : in front of it .

The parser points to the line in question and marks the first error found with a small arrow.

abnormal

Even if the syntax of a Python program is correct, errors may occur when running it. Errors detected during runtime are called exceptions.

Most exceptions will not be handled by the program and are displayed as error messages here:

>>> 10 * (1/0)             # 0 不能作为除数,触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3             # spam 未定义,触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2               # int 不能与 str 相加,触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

Exceptions occur in different types, which are printed as part of the message: the types in the example are ZeroDivisionError, NameError and TypeError.

The first 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

Exception catching can use try/except statement.
Insert image description here
The following example allows the user to enter a legal integer, but allows the user to interrupt the program (using Control-C or the method provided by the operating system). User-interrupted information raises a KeyboardInterrupt exception.

while True:
    try:
        x = int(input("请输入一个数字: "))
        break
    except ValueError:
        print("您输入的不是数字,请再次尝试输入!")

The try statement works as follows:

  • First, the try clause (the statement between the keyword try and the keyword except) is executed.
  • If no exception occurs, the except clause is ignored and the try clause is executed and ends.
  • If an exception occurs during execution of the try clause, the remainder of the try clause will be ignored. If the exception type matches the name after except, the corresponding except clause will be executed.
  • If an exception does not match any except, then the exception will be passed to the upper try.

A try statement may contain multiple except clauses to handle different specific exceptions. At most one branch will be executed.

The handler will only handle exceptions in the corresponding try clause, not exceptions in other try handlers.

An except clause can handle multiple exceptions at the same time. These exceptions will be placed in parentheses to form a tuple, for example:

except (RuntimeError, TypeError, NameError):
    pass

The last except clause can ignore the exception name, which will be used as a wildcard. You can use this method to print an error message and then throw the exception again.

import sys

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

The try/except statement also has an optional else clause. 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.
Insert image description here
The following example determines whether the file can be opened in the try statement. If no exception occurs when opening the file, the else part of the statement is executed and the file content is read:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

It is better to use the else clause than to put all statements in the try clause. This can avoid some unexpected exceptions that except cannot catch.

Exception handling not only handles exceptions that occur directly in the try clause, but also handles exceptions thrown in functions called in the clause (even functions called indirectly). For example:

>>> def this_fails():
        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 will execute the last code regardless of whether an exception occurs.
Insert image description here
In the following example, the finally statement will be executed regardless of whether an exception occurs:

try:
    runoob()
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('这句话,无论异常是否发生都会执行。')

throw an exception

Python uses the raise statement to throw a specified exception.

The syntax format of raise is as follows:

raise [Exception [, args [, traceback]]]

Insert image description here
The following example triggers an exception if x is greater than 5:

x = 10
if x > 5:
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

Executing the above code will trigger an exception:

Traceback (most recent call last):
  File "C:\Users\Lenovo\Desktop\test.py", line 3, in <module>
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 5。x 的值为: 10

The only argument to raise specifies the exception to be thrown. It must be an instance of an exception or an exception class (that is, a subclass of Exception).

If you just want to know if an exception was thrown and don't want to handle it, a simple raise statement can throw it again.

>>> try:
        raise NameError('HiThere')  # 模拟一个异常。
    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 exception

You can have your own exceptions by creating a new exception class. The exception class inherits from the Exception class and can be inherited directly or indirectly, for example:

>>> class MyError(Exception):
        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 class Exception is overridden.

When creating a module that may throw many different exceptions, a common approach is to create a base exception class for the package, and then create different subclasses based on this base class for different error conditions:

class Error(Exception):
    """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.

Define cleanup behavior

The try statement also has an optional clause that defines cleanup behavior that will be performed regardless of the circumstances. For example:

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print('Goodbye, world!')
... 
Goodbye, world!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

In the above example, the finally clause will be executed regardless of whether an exception occurs in the try clause .

If an exception is thrown in a try clause (or in an except or else clause) without any except catching it, then the exception will be thrown after the finally clause is executed.

Here is a more complex example ( containing except and finally clauses in the same try statement ):

>>> def divide(x, y):
        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 cleaning behaviors

Some objects define standard cleanup behavior. Regardless of whether the system successfully uses it, once it is no longer needed, this standard cleanup behavior will be executed.

The following example shows an attempt to open a file and then print the contents to the screen:

for line in open("myfile.txt"):
    print(line, end="")

The problem with the above code is that after execution, the file remains open and is not closed.

The keyword with statement can ensure that objects such as files will correctly execute their cleanup methods after use:

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

After the above code is executed, file f will always be closed even if something goes wrong during processing.

with keyword

The with statement in Python is used for exception handling, encapsulating the try...except...finally coding paradigm, improving ease of use.

The with statement makes the code clearer and more readable, and it simplifies the management of public resources such as file streams.

It is a good practice to use the with keyword when working with file objects .

We can look at the following code examples:
do not use with , nor use try...except...finally

file = open('./test.txt', 'w')
file.write('hello world !')
file.close()

If an exception occurs during the call to write in the above code, the close method will not be executed, so the resources will always be occupied by the program and cannot be released. Next we can use try...except...finally to improve the code:

file = open('./test.txt', 'w')
try:
    file.write('hello world')
finally:
    file.close()

In the above code, we try to capture the code where exceptions may occur. When an exception occurs, the except code block is executed. The finally code block will be executed no matter what the situation, so the file will be closed and resources will not be occupied due to execution exceptions.

Use the with keyword:

with open('./test.txt', 'w') as file:
    file.write('hello world !')

Using the with keyword, the system will automatically call the f.close() method. The function of with is equivalent to the try/finally statement.

We can check whether the file is closed after executing the with keyword:

>>> with open('./test.txt') as f:
...     read_data = f.read()

>>> # 查看文件是否关闭
>>> f.closed
True

The implementation principle of the with statement is based on the context manager.

A context manager is a class that implements the enter and exit methods.

Use the with statement to ensure that the exit method is called at the end of the nested block .

This concept is similar to the use of try...finally blocks.

with open('./test.txt', 'w') as my_file:
    my_file.write('hello world!')

The above example writes hello world! to the ./test.txt file.

The _ enter _ and _ exit _ methods are defined in the file object , that is, the file object also implements the context manager. First, the _ enter _ method is called, then the code in the with statement is executed, and finally the _ exit _ method is called. Even if an error occurs, the exit method will be called , which means the file stream will be closed.

assert

Python assert is used to evaluate an expression and trigger an exception when the expression condition is false.

Assertions can directly return an error when the conditions are not met for the program to run, without having to wait for the program to crash after running. For example, our code can only run under the Linux system, and we can first determine whether the current system meets the conditions.
Insert image description here
The syntax format is as follows:

assert expression

Equivalent to:

if not expression:
    raise AssertionError

assert can also be followed by parameters:

assert expression, [arguments]

Equivalent to:

if not expression:
    raise AssertionError(arguments)

The following are examples of assert usage:

>>> assert True     # 条件为 true 正常执行
>>> assert False    # 条件为 false 触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> assert 1==1    # 条件为 true 正常执行
>>> assert 1==2    # 条件为 false 触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

>>> assert 1==2, '1 不等于 2'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: 1 不等于 2
>>>

The following example determines whether the current system is Linux. If the conditions are not met, an exception will be triggered directly without executing the following code:

import sys
assert ('linux' in sys.platform), "该代码只能在 Linux 下执行"

Guess you like

Origin blog.csdn.net/weixin_40986713/article/details/132894775