1. Problem
Whether developing large-scale programs or automating the developer's own daily chores, it is inevitable to encounter bugs, issues that were not considered before, system failures, and so on. At this time, it is necessary to keep the program as stable as possible, complete the basic cleanup, and provide clear clues of the problem stack and running logs, which is convenient for analysis and troubleshooting. Python's exception handling provides such a mechanism.
2. Processing flow
The basic syntax of exception handling in python is as follows:
try : <normal running program logic> except <exception type 1> : <exception type 1 handling> except <exception type...> : <exception type...handling> except <exception type N> : <exception type N processing> except : <unknown type type processing> else : <program logic that needs to be run in addition to exceptions> finally : <final processing and cleanup required for either normal or exception>
The python system provides some basic exception types, and each python package generally provides corresponding custom exceptions, and developers can also define their own exception types.
Exceptions can also be generated in python programs:
>>> raise NameError('true') Traceback (most recent call last): File "<pyshell#17>", line 1, in <module> raise NameError('true') NameError: true
2.1. Syntax exception: SyntaxError and NameError
Syntax exceptions are a common problem when running python code.
Sometimes the keyword used is wrong, or the variable is undefined, the system will report NameError. For example, in the following example, true is not the python keyword True , nor is it a defined variable:
>>> while true: print (0/0) Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> while true: NameError: name 'true' is not defined
Sometimes it is a syntax problem, and the system will report a SyntaxError:
>>> if True SyntaxError: invalid syntax
In this example, the ':' terminating character required by the conditional line is missing.
2.2. Basic system exception types
The python system provides some basic exception types, the following are some typical built-in system exceptions:
- AssertError:
assert
Statement error - EOFError: input input() encountered end of file
- FloatingPointError: floating point number error
- ImportError/ModuleNotFoundError: Error loading package
- IndexError: index out of bounds
- KeyError: The key to query does not exist in the dictionary, you can use the in keyword to check
- NameError: cannot find local or global variable
- NotImplementedError: The call does not define a method, which is a subclass of RuntimeError
- OSError: System call error, such as I/O, or out of hard disk space
- OverflowError: Numerical computation overflowed
- RuntimeError: Error running
- SystemError:
- TypeError: wrong type
- UnicodeError: unicode encoding and decoding errors
- ValueError: Numeric type mismatch
- ZeroDivisionError: divisor is 0
All python system built-in exceptions are available in the following documentation:
[python3]:https://docs.python.org/3/library/exceptions.html#bltin-exceptions
[python2]:https://docs.python.org/2/library/exceptions.html#bltin-exceptions
2.3, custom exception type
A python program can define its own exception, so that the user of the program can do special processing for this exception. For example, a network connection error can be retried.
class Error(Exception): """Defines the base error class for this module . """ pass class InputError(Error): """Error input . Attributes: expression -- the input expression in error message -- the message of the error """ def __init__(self, expression, message): self.expression = expression self.message = message class StateTransitionError(Error): """The system performed an incorrect state transition . Attributes: previous -- initial state next -- future state message -- state transition error message """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message
2.4, get system error information
The exception types provided by the python system or other packages will provide error information. But sometimes it's not enough. For example, we need to get the access stack of the system, and we need to get some information about the running status of the system.
We can use the traceback package to get access stack information:
import traceback def get_calltrace(): try: a = 1 b = 0 c = a/b except: tb = traceback.format_exc() else: tb = "No error" finally: print (tb) >>> get_calltrace() Traceback (most recent call last): File "<pyshell#28>", line 5, in get_calltrace ZeroDivisionError: division by zero
Sometimes, you need to get more information from the system, you can call sys.exc_info():
import sys, traceback
def get_calltrace(): try: a = 1 b = 0 c = a/b except: tb = traceback.format_exc() exc= sys.exc_info() else: tb = "No error" exc = None finally: print (tb) if exc: print (exc[0]) print (exc[1]) print (exc[2])
3, assert and parameter checking
When we design programs, we often need to consider how to make the system more stable, help developers find problems as early as possible, and let end customers have the best experience.
- assert: Mainly used for internal development, used to verify assumptions and help program design find problems as early as possible.
- Parameter check: It is mainly used for external API development and is used to verify input parameters and help program design to find problems as soon as possible; the calling program must check whether the return value is wrong.
3.1、assert
An unchecked function will always fail, and the error message cannot be controlled:
def add(a, b): return a + b >>> add('hello', 7) Traceback (most recent call last): File "<pyshell#45>", line 1, in <module> add('hello', 7) File "<pyshell#44>", line 2, in add return a + b TypeError: must be str, not int
We can use assert to verify the validity of the call input and provide clear hints:
def add_assert(a, b): assert isinstance(a, (int, float)), "a isn't numeric" assert isinstance(b, (int, float)), "b isn't numeric" return a + b >>> add_assert('hello', 7) Traceback (most recent call last): File "<pyshell#69>", line 1, in <module> add_assert('hello', 7) File "<pyshell#68>", line 2, in add_assert assert isinstance(a, (int, float)), "a isn't numeric" AssertionError: a isn't numeric
3.2, parameter check
If a function is an open API, it needs to do input checking and return an error code to prompt the caller:
def add_validate(a, b): if not isinstance(a, (int, float)): return ("Fail", "a isn't numeric") if not isinstance(b, (int, float)): return ("Fail", "b isn't numeric") return ("OK", a+b) >>> add_validate('hello', 7) ('Fail', "a isn't numeric") >>> add_validate(5.0, 7) ('OK', 12.0)
4. Issues that need to be paid attention to
Exceptions will always occur, and unknown exceptions must be caught and handled in the program, otherwise the system will crash.
When catching exceptions, you need to catch special exceptions first, and then catch common, unknown exceptions last.
Remember to release the allocated resources in the finally statement. Although python has garbage collection processing logic, not releasing resources in time is the main cause of memory leaks in python programs.