"Learning Python with You Hand in Hand" 36-Error and Exception Handling

In the previous article "Learning Python with You Hand in Hand" 35-Data Storage , we learned the methods of storing and reading JSON data.

Today, we will introduce a relatively independent piece of content, that is, error and exception handling. It is very important that we can handle errors and exceptions gracefully when we run programs, especially when we run programs in front of users.

But some people may ask, since the program is already facing users, why are there errors? Various errors and abnormal situations should be resolved when the program is developed or tested at least?

Everyone is right. We do need to deal with errors in the program during development and testing, but this "error" is not the same as the "errors and exceptions" we will introduce today. The former refers more to the "error" that we did not expect and should be resolved but not resolved; while the latter is a part of the normal operation of the program.

If the operation of a program is based on the program developer, it is good that the developer can deal with various potential problems in advance through testing. But if a program needs to rely on user input at the same time, what the user inputs may be difficult for the program developer to control.

For example, when the user is required to enter a number for calculation and the user enters a text, the program will inevitably report an error interrupt; when the user is required to enter a divisor, but the user enters a 0, it will obviously also report an error interrupt.

This kind of "error" that is not under the control of the program developer but may appear is an unavoidable "false error" during the operation of the program, which requires us to pre-process or remind us through some means.

For example, when it is detected that the user should enter a number but enter text, or the divisor enters 0, the user needs to be prompted to re-enter instead of the program being interrupted by an error.

If the "false errors" that may be brought about by the user's various input conditions are not considered in advance, and the program is truly reported to be interrupted by the error, it is a "true error", which should be avoided as a program developer.

After understanding the "true and false" errors, let's take a look at how Python handles various errors and exceptions gracefully.

1. Error type

There are many types of errors in a program. In addition to the two mentioned just now, it is also possible that the file does not exist when reading the file; I want to get the key value of the dictionary but the data type is a tuple; I want to get the first of the list. The value of 3 elements but the length of the list is only 2. Even the print() is written as pring(), the if statement is not written ":" or is not indented, etc.

If you want to know what type of error occurred in the program, you can get it through the prompt message when the program reports an error.

When a general program reports an error, a Traceback error message will appear. In the previous examples, we have encountered a lot, but at that time we did not specify the type of error.

Generally speaking, the error type will be displayed at the beginning of the first or last line of the error message. If it is not a Traceback type of error message, it will generally be displayed at the beginning of the error message, and it will be more obvious.

Let's take a look at the types of errors in the several situations just mentioned.

In [1]: a = input()
        print("{}".format(int(a) + 1))
        
好

Out[1]: ---------------------------------------------------------------------------
        ValueError                                Traceback (most recent call last)
        <ipython-input-12-345a07f0f289> in <module>
              1 a = input()
        ----> 2 print("{}".format(int(a) + 1))
        
        ValueError: invalid literal for int() with base 10: '好'
In [2]: b = input()
        print("{}".format(2 / int(b)))
        
0

Out[2]: ---------------------------------------------------------------------------
        ZeroDivisionError                         Traceback (most recent call last)
        <ipython-input-13-e805a437abde> in <module>
              1 b = input()
        ----> 2 print("{}".format(2 / int(b)))
        
        ZeroDivisionError: division by zero
In [3]: with open("c.txt") as f:
            f.read()
Out[3]: ---------------------------------------------------------------------------
        FileNotFoundError                         Traceback (most recent call last)
        <ipython-input-16-c0989807bcdb> in <module>
        ----> 1 with open("c.txt") as f:
              2     f.read()
        
        FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
In [4]: d = (1, 2, 3)
        print(d.keys())
Out[4]: ---------------------------------------------------------------------------
        AttributeError                            Traceback (most recent call last)
        <ipython-input-25-aaf87b00f26d> in <module>
              1 d = (1, 2, 3)
        ----> 2 print(d.keys())
        
        AttributeError: 'tuple' object has no attribute 'keys'
In [5]: e = [1, 2]
        print(e[2])
Out[5]: ---------------------------------------------------------------------------
        IndexError                                Traceback (most recent call last)
        <ipython-input-28-0cf415846369> in <module>
              1 e = [1, 2]
        ----> 2 print(e[2])
        
        IndexError: list index out of range
In [6]: pring("f")
Out[6]: ---------------------------------------------------------------------------
        NameError                                 Traceback (most recent call last)
        <ipython-input-29-91beadee65e4> in <module>
        ----> 1 pring("f")
        
        NameError: name 'pring' is not defined

 

 

 

In [7]:if 1 < 2
            print("g")
Out[7]:   File "<ipython-input-33-2b4de2cf9d7c>", line 1
            if 1 < 2
                    ^
        SyntaxError: invalid syntax
In [8]: if 1 < 2:
        print("h")
Out[8]:   File "<ipython-input-34-221bcba245b3>", line 2
            print("h")
            ^
        IndentationError: expected an indented block

The above lists 8 examples of common errors, each of which has different error types, including ValueError, ZeroDivisionError, FileNotFoundError, AttributeError, IndexError, NameError, SyntaxError, IdentificationError, etc., which can be easily found in the error message.

There are many types of errors that may occur in a program. It is difficult to list them one by one, and it is not necessary. The important thing is to be able to deal with the possible errors. This is what we will introduce below.

2. Try-except code block

In Python, try-except is a code block that specializes in handling exceptions. This code block allows Python to perform specified operations and tells Python how to deal with exceptions. When using the try-except code block, even if an exception occurs, the program can continue to run, instead of interrupting the program by an error message like the above.

When using the try-except code block, you can put the code that may cause the error in the try code block. If the code in the try code block does not appear abnormal, the program can continue to run normally; if the code in the try code block has an error , Python will automatically execute the code block in except to avoid program errors and interruptions.

Let's take a look at how to use try-except to avoid the above exceptions.

In [9]: a = input("请输入一个数字:")
        try:
            print("{}".format(int(a) + 1))
        except:
        print("输入错误,请重新输入")
Out[9]: 请输入一个数字:好
        输入错误,请重新输入

We put the print statement print("{}".format(int(a) + 1)) that may cause program errors in the try code block. If the user's input does not cause an exception, the result can be printed normally. If the user's input causes an exception, it will trigger the execution of the except code block print ("input error, please re-enter"), prompting the user to re-enter, avoiding the interruption of the previous error message, this is the try-except code The role of blocks.

Although no error will be reported after applying the try-except code block, the current program is not perfect. The program actually ends after prompting the user to re-enter, and there is no chance to re-enter it. So we use the basic knowledge we learned before, and then perfect this program, with the application of the try-except code block, we can achieve a more perfect effect.

In [10]: while True:
             a = input("请输入一个数字")
             try:
                 print("{}".format(int(a) + 1))
                 print("程序结束!")
                 break
             except:
                 print("输入错误,请重新输入")
Out[10]: 请输入一个数字 好
         输入错误,请重新输入
         请输入一个数字 1
         2
         程序结束!

From the above two examples, we can see that the try-except code block can effectively handle the abnormalities that may occur in the program and the user input process, and make the program run normally without the user feeling, and continue to execute the try-except The code behind the code block.

3、else

In addition to the try and except two code blocks, it can also execute other specific codes for situations where no exception occurs. We can put this part of the code in the else code block.

That is to say, when no exception occurs in the try part of the code, the code in the else part continues to be executed. If an exception occurs in the try part of the code, only the code in the except part is executed, and the code in the else part is skipped, and the code after the try-except-else code block is executed.

In [11]: while True:
             a = input("请输入一个数字")
             try:
                 print("{}".format(int(a) + 1))
             except:
                 print("输入错误,请重新输入")
             else:
                 print("程序结束!")
                 break
Out[11]: 请输入一个数字 1
         2
         程序结束!

With the else code block, we can put some of the statements that were previously placed in the try code block in the else code block.

But the problem came again.

There is no difference between this structure and the previous effect when there is no else code block. On the premise that no exception occurs, since the try part and the else part are executed under normal conditions, why are they divided into two parts? Put the statement to be executed in the else code block after the statement that may be abnormal in the try. If no exception occurs, the effect is not the same?

That's right, according to the order in which the statements are executed, this is indeed the case. But from the normative usage of the try statement block, this part of the statement is mainly the code that may be abnormal, instead of putting other statements that need to be executed when no exception occurs. This is the true meaning of try-since you want to try (try), put the code that may be wrong here to try it out, and put it in the else to execute the statement that needs to be run when no exception occurs.

Summarize the execution process of the try-except-else code block:

Python will first try the statements in the try code block, and only the statements that may cause an exception are placed in the try code block. When the code in the try code block is successfully executed, Python will run the statements in the else code block. The statements here are all statements that depend on the successful execution of the try code block. If Python tries to run the statement in the try code block and an error occurs, the statement in the except code block will be executed. Finally, Python will jump out of the entire try-except-else code block and continue to execute the following program.

4、except

In the except code block, in addition to the effect of executing the part of the code when an exception occurs, you can also specify that the part of the code is executed only when one or more specific errors occur.

For example, if you should enter a number but a ValueError error message appears after entering the text, you can specify the statement to be executed when the error type occurs. But for other errors that may be caused, you may report an error and interrupt the program as if you did not use the try-except code block.

In [12]: while True:
             b = input("请输入一个数字")
             try:
                 print("{}".format(2 / int(b)))
             except ValueError:   # 只处理ValueError的异常情况
                 print("输入错误,请输入一个数字")
             else:
                 print("程序结束!")
                 break
Out[12]: 请输入一个数字 好
         输入错误,请输入一个数字
         请输入一个数字 0
         ---------------------------------------------------------------------------
         ZeroDivisionError                         Traceback (most recent call last)
         <ipython-input-1-7e415183992c> in <module>
               2     b = input("请输入一个数字")
               3     try:
         ----> 4         print("{}".format(2 / int(b)))
               5     except ValueError:   # 只处理ValueError的异常情况
               6         print("输入错误,请输入一个数字")
         
         ZeroDivisionError: division by zero

Since the above example only deals with the exception of ValueError, when the user enters text, a ValueError exception occurs, the except code block is executed, the user is prompted to re-enter, and the program continues to run. But when the user enters 0, because the error type that appears is ZeroDivisionError, which is not within the processing range of the except code block, it will report an error and interrupt the program as usual.

If you want to perform different except operations for different error types, you can use a try with multiple except statement blocks to implement different processing methods for different exceptions, so that you can provide users with more targeted error prompts and guide The user entered correctly.

In [13]: while True:
             b = input("请输入一个数字")
             try:
                 print("{}".format(2 / int(b)))
              except ValueError:
                 print("输入错误,请勿输入非数字字符")
             except ZeroDivisionError:
                 print("输入错误,0不能做除数")
             else:
                 print("程序结束!")
                 break
Out[13]: 请输入一个数字 好
         输入错误,请勿输入非数字字符
         请输入一个数字 0
         输入错误,0不能做除数
         请输入一个数字 2
         1.0
         程序结束!

If you want to specify multiple errors and use the same processing method, you can use a tuple to enumerate the specified multiple errors. At this time, when any error in the tuple occurs, the same except statement block will be executed.

In [14]: while True:
             b = input("请输入一个数字")
             try:
                  print("{}".format(2 / int(b)))
             except (ValueError, ZeroDivisionError):   # 同时处理ValueError和ZeroDivisionError的异常情况
                  print("输入错误,请输入非0数字")
             else:
                  print("程序结束!")
                  break
Out[14]: 请输入一个数字 好
         输入错误,请输入非0数字
         请输入一个数字 0
         输入错误,请输入非0数字
         请输入一个数字 2
         1.0
         程序结束!

At this point, although the program can handle the exceptions of ValueError and ZeroDivisionError at the same time, if other errors occur, it will still report an error and interrupt the program. Therefore, when using except to specify the error type, you must ensure that it does not exceed the specified error type. If another unspecified error type occurs and the program is interrupted, it is a "true error".

5、finally

The finally code block contains statements that need to be executed regardless of whether an exception occurs, and it is mandatory.

In most cases, the effect is the same as not putting it in the finally block but outside the entire try-except code block. But why do you need this code block, and there is another sentence to enforce it later?

Let's take a look at the following examples first and compare the similarities and differences.

In [15]: while True:
             b = input("请输入一个数字")
             try:
                 print("{}".format(2 / int(b)))
             except (ValueError, ZeroDivisionError):   # 同时处理ValueError和ZeroDivisionError的异常情况
                 print("输入错误,请输入非0数字")
             else:
                 print("程序结束!")
                 break
             finally:
                 print("谢谢您的使用!")
Out[15]: 请输入一个数字 好
         输入错误,请输入非0数字
         谢谢您的使用!
         请输入一个数字 0
         输入错误,请输入非0数字
         谢谢您的使用!
         请输入一个数字 2
         1.0
         程序结束!谢谢您的使用!
In [16]: while True:
             b = input("请输入一个数字")
             try:
                 print("{}".format(2 / int(b)))
             except (ValueError, ZeroDivisionError):   # 同时处理ValueError和ZeroDivisionError的异常情况
                  print("输入错误,请输入非0数字")
             else:
                 print("程序结束!")
                 break
             print("谢谢您的使用!")
Out[16]: 请输入一个数字 好
         输入错误,请输入非0数字
         谢谢您的使用!
         请输入一个数字 0
         输入错误,请输入非0数字
         谢谢您的使用!
         请输入一个数字 2
         1.0
         程序结束!

In the above two examples, one is to put print ("Thank you for your use!") in the finally code block, and the other is to put the try-except code block outside.

The difference in execution is that when it is placed in the finally code block, although the break statement is executed in the else code block, the statement in the finally code block is forced to execute and the result is printed; it is not placed in the finally code When in the block, after the break statement is made in the else code block, the whole loop is over, and the statements outside the try-except code block will not be executed.

Therefore, in this case where there is a termination program, it makes a difference whether the statement is placed in the finally code block.

As for whether there is a difference in other cases, you need to carefully judge during program execution, and decide whether to put it in the finally code block or outside the try-except code block according to the needs of the program.

6. Silent failure

The so-called silent failure means that when an exception occurs in the program and the except code block is executed, there is no code to be executed. At this time, the pass statement can be used as a statement in the except code block. If it is left blank, an error will be reported.

Silent failure is mainly used in situations where there is no need to inform the user that there is an exception, such as starting a program but an exception occurs. At this time, there is no need to tell the user what exception the program will do next, but directly handle it so that the user does not feel it. The exception that occurred.

In [17]: for i in range(-2,3):
             try:
                 print("{}".format(2 / i))
             except:
                 pass   # 出现异常后不进行任何提示
             else:
                 print("计算完成!")
Out[17]: -1.0
         计算完成!
         -2.0
         计算完成!
         2.0
         计算完成!
         1.0
         计算完成!

In the above example, although the divisor is 0, no statement indicating an exception is executed, and the entire program is executed smoothly as if no exception occurred.

But like the previous examples, it is not suitable to use this silent failure method. Especially in the process of interacting with the user, if there is no error prompt but the program cannot continue to run, the user will be very confused and do not know what to do next, so we still have to decide whether to use it according to different situations. The way of silent failure.

The above is our introduction to error and exception handling methods. At this point, the explanation of the basic knowledge of Python is basically over. In the next article, we will do an applied review of what we have learned recently, and experience the process of program refactoring with you through an example, so stay tuned.

 

image

 


Thanks for reading this article! If you have any questions, please leave a message and discuss together ^_^

To read other articles in the "Learning Python with You Hand in Hand" series, please follow the official account and click on the menu selection, or click the link below to go directly.

"Learning Python with You Hand in Hand" 1-Why learn Python?

"Learning Python with you hand in hand" 2-Python installation

"Learning Python with You Hand in Hand" 3-PyCharm installation and configuration

"Learning Python with You Hand in Hand" 4-Hello World!

"Learning Python with You Hand in Hand" 5-Jupyter Notebook

"Learning Python with You Hand in Hand" 6-String Identification

"Learning Python with You Hand in Hand" 7-Index of Strings

"Learning Python with You Hand in Hand" 8-String Slicing

"Learning Python with You Hand in Hand" 9-String Operations

"Learning Python with You Hand in Hand" 10-String Functions

"Learning Python with You Hand in Hand" 11-Formatted Output of Strings

"Learning Python with You Hand in Hand" 12-Numbers

"Learning Python with You Hand in Hand" 13-Operation

"Learning Python with You Hand in Hand" 14-Interactive Input

"Learning Python with You Hand in Hand" 15-judgment statement if

"Learning Python with You Hand in Hand" 16-loop statement while

"Learning Python with You Hand in Hand" 17-the end of the loop

"Learning Python with You Hand in Hand" 18-loop statement for

"Learning Python with You Hand in Hand" 19-Summary of the first stage

"Learning Python with You Hand in Hand" 20-List

"Learning Python with You Hand in Hand" 21-Tuples

"Learning Python with You Hand in Hand" 22-Dictionary

"Learning Python with You Hand in Hand" 23-Built-in Sequence Function

"Learning Python with You Hand in Hand" 24-Collection

"Learning Python with You Hand in Hand" 25-List Comprehension

"Learning Python with You Hand in Hand" 26-Custom Functions

"Learning Python with You Hand in Hand" 27-Parameters of Custom Functions

"Learning Python with You Hand in Hand" 28-the return value of a custom function

"Learning Python with You Hand in Hand" 29-Anonymous Functions

"Learning Python with You Hand in Hand" 30-Module

"Learning Python with You Hand in Hand" 31-File Opening

"Learning Python with You Hand in Hand" 32-File Reading

"Learning Python with You Hand in Hand" 33-closing the file

"Learning Python with You Hand in Hand" 34-File Writing

"Learning Python with You Hand in Hand" 35-Data Storage

For Fans: Follow the "also said Python" public account, reply "hand 36", you can download the sample sentences used in this article for free.

Also talk about Python-a learning and sharing area for Python lovers

Guess you like

Origin blog.csdn.net/mnpy2019/article/details/111658315