Getting started with Python: Python's built-in exception mechanism

The rest of this chapter will specifically introduce Python's built-in exception mechanism. The entire Python exception mechanism is built in accordance with object-oriented specifications, which makes it flexible and extensible. Even if everyone is not familiar with object-oriented programming (OOP), there is no need to learn object-oriented technology when using exceptions.

Exceptions are raiseobjects automatically generated by Python functions . After the exception object is generated, the raisestatement that caused the exception will change the execution mode of the Python program, which is different from the normal execution flow. Instead of continuing to execute raisethe next statement, or executing the next statement after the exception is generated, it retrieves the current function call chain and finds a handler that can handle the current exception. If an exception handler is found, it will be called and the exception object will be accessed for more information. If no suitable exception handler is found, the program will abort and report an error.

{Easy to request and hard to recognize!}

In general, Python's approach to error handling is different from common approaches in languages ​​such as Java. Those languages ​​rely on checking out as much as possible before the error occurs, because handling the exception after the error occurs often requires a variety of high costs. This approach has been introduced in the first section of this chapter, and is sometimes called the "Look Before You Leap" (LBYL) approach.

However, Python may rely more on "exceptions" and deal with errors after they occur. Although this dependency may seem risky, if the "exception" can be used properly, the code will be lighter and more readable, and will only be processed when an error occurs. This Python-style error handling method is often called "Easier to Ask Forgiveness than Permission" (EAFP).

14.2.1 Types of Python Exceptions

In order to correctly reflect the actual cause of the error, or the abnormal situation that needs to be reported, various types of abnormal objects can be generated. There are many types of exception objects provided by Python 3.6:

 
  1. BaseException
  2. SystemExit
  3. KeyboardInterrupt
  4. GeneratorExit
  5. Exception
  6. StopIteration
  7. ArithmeticError
  8. FloatingPointError
  9. OverflowError
  10. ZeroDivisionError
  11. AssertionError
  12. AttributeError
  13. BufferError
  14. EOFError
  15. ImportError
  16. ModuleNotFoundError
  17. LookupError
  18. IndexError
  19. KeyError
  20. MemoryError
  21. NameError
  22. UnboundLocalError
  23. OSError
  24. BlockingIOError
  25. ChildProcessError
  26. ConnectionError
  27. BrokenPipeError
  28. ConnectionAbortedError
  29. ConnectionRefusedError
  30. ConnectionResetError
  31. FileExistsError
  32. FileNotFoundError
  33. InterruptedError
  34. IsADirectoryError
  35. NotADirectoryError
  36. PermissionError
  37. ProcessLookupError
  38. TimeoutError
  39. ReferenceError
  40. RuntimeError
  41. NotImplementedError
  42. RecursionError
  43. SyntaxError
  44. IndentationError
  45. TabError
  46. SystemError
  47. TypeError
  48. ValueError
  49. UnicodeError
  50. UnicodeDecodeError
  51. UnicodeEncodeError
  52. UnicodeTranslateError
  53. Warning
  54. DeprecationWarning
  55. PendingDeprecationWarning
  56. RuntimeWarning
  57. SyntaxWarning
  58. UserWarning
  59. FutureWarning
  60. ImportWarning
  61. UnicodeWarning
  62. BytesWarningException
  63. ResourceWarning

Python's exception objects are constructed hierarchically, and the indentation in the above exception list illustrates this point. As shown in Chapter 10 __builtins__, an alphabetical list of exception objects can be obtained from the module.

Each exception is a Python class, inherited from the parent exception class. But if you have not been exposed to OOP, don't worry. For example, IndexErroralso LookupErrorclasses and Exceptionclasses (through inheritance), and still BaseException.

This hierarchical structure is intentional, most exceptions are inherited from Exception, it is strongly recommended that all user-defined exceptions should also be Exceptionsubclasses, not BaseExceptionsubclasses. The reason is as follows.

 
  1. try:
  2. # 执行一些异常操作
  3. except Exception:
  4. # 处理异常

{:—} In the above code, you can still use Ctrl+C to suspend trythe execution of the statement block without causing exception handling code. Because the KeyboardInterruptexception is not Exceptiona subclass.

Although the explanation of each exception can be found in the documentation, the most common exceptions can be quickly familiarized with hands-on programming.

14.2.2 Throw an exception

Exceptions can be raised by many Python built-in functions:

 
  1. >>> alist = [1, 2, 3]
  2. >>> element = alist[7]
  3. Traceback (innermost last):
  4. File "<stdin>", line 1, in ?
  5. IndexError: list index out of range

Python's built-in error checking code will detect that the index value of the list requested to be read in the second line does not exist and raise IndexErroran exception. The exception is always passed back to the top layer, which is the interactive Python interpreter, and the interpreter handles it by printing a message indicating that an exception has occurred.

In your own code, you can also use raisestatements to explicitly raise exceptions. raiseThe most basic form of the statement is as follows:

 
  1. raise exception(args)

exception(args)Part of it will create an exception object. The parameters of the new exception object should usually be values ​​that help determine the error condition, as will be introduced later. After the exception object is created, it raisewill be thrown up the Python function stack, which is raisethe function currently executed to the statement. The newly created exception will be thrown to the closest type of exception catching code block on the stack. If the corresponding exception catching code block is not found until the top level of the program, the program will stop running and report an error. In the interactive session, the error message will be printed to the console.

Please try the following code:

 
  1. >>> raise IndexError("Just kidding")
  2. Traceback (innermost last):
  3. File "<stdin>", line 1, in ?
  4. IndexError: Just kidding

raiseThe messages generated above seem to be similar to all previous Python list index error messages at first glance. A closer look will reveal that this is not the case. The actual error is not as serious as the previous error.

String parameters are often used when creating exceptions. If the first parameter is given, most of the built-in Python exceptions will think that the parameter is the information to be displayed as an explanation of the event that has occurred. However, this is not always the case, because each exception type has its own class, and the parameters required to create an exception of that class are completely determined by the definition of the class. In addition, custom exceptions created by programmers are often used for purposes other than error handling, so text messages may not be used as parameters.

14.2.3 Catch and handle exceptions

The point of the exception mechanism is not to stop the program with an error message. It is never difficult to implement the abort function in the program. The special feature of the exception mechanism is that it does not necessarily stop the program from running. By defining appropriate exception handling code, you can ensure that common exceptions will not cause the program to fail. It may be possible to display an error message or other methods to the user, or it may be possible to solve the problem without causing the program to crash.

The following illustrates the basic syntax of Python exception is caught and handled, uses try, and exceptsometimes by elsekeyword:

 
  1. try:
  2. body
  3. except exception_type1 as var1:
  4. exception_code1
  5. except exception_type2 as var2:
  6. exception_code2
  7. .
  8. .
  9. .
  10. except:
  11. default_exception_code
  12. else:
  13. else_body
  14. finally:
  15. finally_body

The first part of the trystatement is executed body. If the execution is successful, that is, the trystatement did not catch an exception thrown, then execute the else_bodypart, and the trystatement is executed. Because there is a finallystatement here , part of it will be executed next finally_body. If an exception is trythrown, each exceptclause will be searched in turn to find the clause that matches the associated exception type with the thrown exception. If a matching exceptclause is found , the thrown exception is assigned to the variable, the variable name is given after the associated exception type, and exceptthe exception handling code in the matching clause is executed . For example, if except exception_type as var:this line matches a thrown exception exc, a variable will be created var, and the value exceptwill be varassigned to before executing the exception handling code of the statement exc. varIt is not necessary, it can only appear except exception_type: this way of writing, a given type of exception can still be caught, but the exception will not be assigned to a variable.

If no matching exceptclause is found , the trystatement cannot handle the thrown exception, and the exception will continue to be thrown to the upper layer of the function call chain, expecting the outer layer tryto handle it.

tryThe last exceptclause in the statement can not specify any exception types at all, so that all types of exceptions will be handled. For some debugging tasks and very fast prototyping, this technique may be convenient. But usually this is not a good practice, all errors are exceptcovered up by clauses, which may make some behaviors of the program difficult to understand.

tryThe elseclauses of the statement are optional and are rarely used. The clause will be executed if and only if no error is thrown when part of the trystatement is executed.bodyelse

tryStatement finallyclause is also optional, in try, except, elseparts are executed after the implementation. If tryan exception is raised in the block and has not been exceptprocessed by any block, finallythe exception will be raised again after the block is executed. Because the finallyblock will always be executed, it can provide an opportunity to add resource cleanup code through operations such as closing the file and resetting variables after the exception handling is completed.

Hands-on: Catch the exception and write code to read the two numbers entered by the user and divide the first number by the second number. Check and catch the exception when the second number is 0 ( ZeroDivisionError).

14.2.4 Customize new exception

Defining your own exception is very simple. It can be done with the following two lines of code:

 
  1. class MyError(Exception):
  2. pass

{:—} The above code creates a class that will inherit Exceptionall the content in the base class . But if you don’t want to clarify the details, you can ignore it.

The above exceptions can be raised, caught, and handled like any other exception. If a parameter is given and it is not captured and processed, the parameter value will be printed at the end of the trace information:

 
  1. >>> raise MyError("Some information about what went wrong")
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. __main__.MyError: Some information about what went wrong

Of course, the above parameters are also accessible in the exception handling code written by yourself:

 
  1. try:
  2. raise MyError("Some information about what went wrong")
  3. except MyError as error:
  4. print("Situation:", error)

The result of the operation will be as follows:

 
  1. Situation: Some information about what went wrong

If an exception is thrown with multiple parameters, these parameters will be passed into the exception handling code in the form of a tuple, and the tuple can be accessed through errorthe argsattributes of the variable :

 
  1. try:
  2. raise MyError("Some information", "my_filename", 3)
  3. except MyError as error:
  4. print("Situation: {0} with file {1}\n error code: {2}".format(
  5. error.args[0],
  6. error.args[1], error.args[2]))

The result of the operation will be as follows:

 
  1. Situation: Some information with file my_filename
  2. error code: 3

The exception type is a regular Python class and inherits from the Exceptionclass, so it is a relatively simple matter to establish your own exception type hierarchy for your own code. When reading this book for the first time, you don't need to care about this process. After reading Chapter 15, you can check back anytime. How to create your own exception is completely determined by requirements. If you are writing a small program that may only generate some unique errors or exceptions, then use the Exceptionsubclass of the class as described above . If you are writing a large, multi-file, specific function code library (such as weather forecast library), you can consider defining a separate WeatherLibraryExceptionclass named , and then define all the different exceptions in the library as WeatherLibraryExceptionsubclasses.

Velocity measurement Topic: "Exception" class assumptions MyErrorinherited from Exceptionclass, I ask except Exception as e, and except MyError as ewhat is the difference?

14.2.5 Using assert statements to debug programs

assertStatement is raisea special form of statement:

 
  1. assert expression, argument

If expressionthe settlement result is Falseand the system variable __debug__is also True, argumentan AssertionErrorexception with optional parameters will be raised . __debug__The variable defaults to True. Start the Python interpreter with -Oor -OOparameter, or set the system variable PYTHONOPTIMIZEto True, you can __debug__set to False. Optional parameters argumentcan be used to place assertthe explanation information.

If __debug__is False, then the code generator will not assertcreate the code statement. In the development phase, you can use assertstatements to cooperate with debugging statements to test the code. assertThe statement can be stored in the code for future use, and there is no running overhead during normal use:

 
  1. >>> x = (1, 2, 3)
  2. >>> assert len(x) > 5, "len(x) not > 5"
  3. Traceback (most recent call last):
  4. File "<stdin>", line 1, in <module>
  5. AssertionError: len(x) not > 5

Hands-on question: assert statement Please write a simple program that allows the user to enter a number, and use the assertstatement to cause an exception when the number is 0. First, please test to ensure assertthe execution of the statement, and then disable it through the methods mentioned in this section assert.

14.2.6 Abnormal inheritance structure

As mentioned before, the exception of Python is a layered architecture. This section will give an in-depth introduction to this architecture, including exceptthe meaning of this architecture for how clauses catch exceptions.

Consider the following code:

 
  1. try:
  2. body
  3. except LookupError as error:
  4. exception code
  5. except IndexError as error:
  6. exception code

Here will be captured IndexErrorand LookupErrorthe two exceptions. It happens to IndexErrorbe LookupErrora subclass. If it is bodythrown IndexError, then the error will be first except LookupError as error:detected by the " " line. Because of IndexErrorinheritance LookupError, the first exceptclause will be successfully executed, and the second exceptclause will never be used because its operating conditions are exceptincluded in the first clause.

On the contrary, exceptit may make sense to reverse the order of the two clauses. Thus the process in the first clause IndexError, the second clause processing other IndexErrorthan LookupError.

14.2.7 Example: Disk writing program written in Python

This section will return to the example of the word processing program. When writing a document to the disk, the program needs to check for insufficient disk space:

 
  1. def save_to_file(filename) :
  2. try:
  3. save_text_to_file(filename)
  4. save_formats_to_file(filename)
  5. save_prefs_to_file(filename)
  6. .
  7. .
  8. .
  9. except IOError:
  10. ...处理错误...
  11. def save_text_to_file(filename):
  12. ...调用底层函数来写入文本大小...
  13. ...调用底层函数来写入实际的文本数据...
  14. .
  15. .
  16. .

Note that the error handling code is very inconspicuous, save_to_fileand is put together with a series of disk write calls in the function. None of those disk write sub-functions need to contain any error handling code. The program will be easier to develop at the beginning, and it is also very simple to add error handling code later. Programmers often do this, although this order of implementation is not optimal.

It is also worth noting that the above code will not only respond to the disk full error, but will respond to all IOErrorexceptions. Python's built-in function will automatically raise IOErroran exception whenever it cannot complete an I/O request, regardless of the reason . This may be enough to meet the needs, but if you want to individually identify the disk is full, you have to do some more operations. You can exceptcheck how much free space the disk has in the statement body. If the disk space is insufficient, it is obvious that a disk full problem has occurred and should exceptbe dealt with in the statement body. If it is not a disk space issue, then exceptthe code in the statement body can throw this IOErrorto the upper layer of the call chain so that it can be handled by other exceptstatement bodies. If this solution is not enough to solve the problem, you can also do some more extreme processing, for example, find the C source code of the Python disk writing function, and raise a custom DiskFullexception as needed . This last solution is not recommended, but it makes sense to know that this possibility exists when necessary.

14.2.8 Example: Abnormality during normal calculation

The most common use of exceptions is to handle errors, but they can also be very useful in situations that should be considered normal calculations. Imagine the problems that may be encountered in the implementation of spreadsheet programs. Like most spreadsheets, the program must be able to perform arithmetic operations involving multiple cells, and it must also allow cells to contain non-numeric values. In this kind of application, the contents of blank cells encountered during numerical calculations may be regarded as 0values. Cells containing any other non-numeric strings may be considered invalid and expressed as Python Nonevalues. Any calculation involving invalid values ​​should return invalid values.

Let's first write a function to evaluate the string in a spreadsheet cell and return the appropriate value:

 
  1. def cell_value(string):
  2. try:
  3. return float(string)
  4. except ValueError:
  5. if string == "":
  6. return 0
  7. else:
  8. return None

Python's exception handling capabilities make this function very simple to write. In the tryblock, the string in the cell is floatconverted to a number with a built-in function, and the result is returned. If the parameter string cannot be converted to a number, the floatfunction throws ValueErroran exception. Then the exception handling code will catch the exception and return 0or None, depending on whether the parameter string is an empty string.

Sometimes it may be necessary Noneto deal with the value during evaluation . The next step is to solve this problem. In a programming language without an exception mechanism, the conventional solution is to define a set of custom arithmetic evaluation functions, check whether the parameters are valid None, and then use these custom functions to replace the built-in functions to perform all spreadsheet calculations. However, this process can be very time-consuming and error-prone. In fact, this is a self-built interpreter in the spreadsheet program, so it will reduce the running speed. This project uses another scheme. All spreadsheet formulas can actually be Python functions. The parameters of the function are the x and y coordinates of the cell being evaluated and the spreadsheet itself. Use standard Python arithmetic operators to calculate the result and cell_valueextract the necessary values ​​from the spreadsheet. . You can define a named safe_applyfunction, tryuse the corresponding parameters in the block to complete the call of the formula, and return the calculation result according to whether the formula is successfully calculated or return None:

 
  1. def safe_apply(function, x, y, spreadsheet):
  2. try:
  3. return function(x, y, spreadsheet)
  4. except TypeError:
  5. return None

The above two changes are sufficient to add Nonethe concept of null ( ) to the semantics of the spreadsheet . If you do not use the exception mechanism to develop the above functions, it will be a very instructive exercise (the implication is that you can experience a considerable amount of work).

14.2.9 Applicable occasions for exceptions

Using exceptions to handle almost all errors is a natural solution. Often the error handling part will be added when the rest of the program is basically completed. Unfortunately, this is the case, but the exception mechanism is very good at writing this kind of post-error handling code in an easy-to-understand way. It is better to add more error handling code after the fact.

If there are calculation branches in the program that are obviously unsustainable, then there may be a large number of processing procedures to be discarded, then the exception mechanism will also be very useful. This is the case with the spreadsheet example. Other application scenarios include branch-and-bound algorithms and parsing algorithms.

Quick test: Will abnormal Python exceptions cause the program to abort?

Suppose you want to access the dictionary object x, if the key does not exist, that is, it is triggered KeyError, then return None. How to write code to achieve this goal?

 

Hands-on question: Exception write code to create a custom ValueTooLarge, and xraise it when the variable is greater than 1000.

This article is excerpted from "Python Quick Start (3rd Edition)"

This is a Python quick start book, written based on Python 3.6. The book is divided into 4 parts. The first part explains the basics of Python and gives a brief introduction to Python; the second part introduces the key points of Python programming, involving lists, tuples, sets, strings, dictionaries, flow control, functions, and modules And scope, file system, exceptions, etc.; the third part explains the advanced features of Python, involving classes and object-oriented, regular expressions, data types, ie objects, packages, Python libraries, etc.; the fourth part focuses on data processing, involving Data file processing, network data, data storage and data exploration, and finally related cases are given.

This book has a clear frame structure, reasonable content layout, a step-by-step explanation, and a large number of examples and exercises, so that readers can quickly learn and master Python. It is not only suitable for Python beginners to learn, but also suitable as a concise Python reference book for professional programmers.

Guess you like

Origin blog.csdn.net/epubit17/article/details/108506470