Look at the following function
def test():
sum =3/0if __name__ =='__main__':test()
Dividing by 0 is definitely wrong, it will trigger an except, the content is as follows:
File “E:\Src\dongsheng\TestPython\testtrace_back.py”, line 23, in <module
test()
File “E:\Src\dongsheng\TestPython\testtrace_back.py”, line 19, in test
sum = 3/0
ZeroDivisionError: integer division or modulo by zero
The above prompt appears when running in the IDE. When the script is actually run online, it will generally be started in nohup mode, and the output content will be written to the nohup.out file, but the content in this file may be very much. Messy, not conducive to abnormal investigation.
Python provides traceback, which can perfectly output the information when the except occurs, just like the above content, and can be input into the specified file, so you might as well write a decorator to modify those functions that need to be supervised, when they happen When abnormal, record the information about the abnormality.
# coding=utf-8from functools import wraps
import traceback
def except_trace(filename):
def decorate(func):
@ wraps(func)
def wrapper(*args,**kwargs):try:func(*args,**kwargs)
except:
fp =open(filename,'w')
traceback.print_exc(file=fp)
fp.close()return wrapper
return decorate
@ except_trace('1.txt')
def test():
sum =3/0if __name__ =='__main__':test()
This time, after an exception occurs, the information about the exception will be entered into the 1.txt file. This file only contains the exception information for easy viewing.
Additional knowledge: Python's except quirks
Let me show off my favorite Python quirks. What do you want this Python code to do?
If you are learning Python from another programming language, you may want the except clause to introduce nested scope, so assigning e in the clause will not affect the e variable already in the outer scope. However, in Python, control structures usually do not introduce nested scope (list comprehensions are an exception), so if you have more Python experience, you might expect it to print an instance of ZeroDivisionError.
In fact, in the standard CPython implementation, it prints nothing; at the same time, the last line will raise a NameError. Is this a bug? In fact, this is intentional. If you look at the bytecode generated by the except clause, you can see:
When the control flow exits the except block, Python will remove the name from the scope. why? Because the exception holds a reference to the current stack frame, the stack frame contains everything in scope. Since Python mainly manages the main memory by reference counting, this means that nothing in the current scope will be released until the next round of garbage collection runs (if any). The current behavior is a compromise between memory usage, ease of implementation, and clean language. It has some drawbacks, but I think it reflects what I like about Python: don't let purity hinder practicality.
But this only explains the DELETE_NAME instruction. Why does CPython set e to None, even if the variable is deleted immediately afterwards? Well, imagine that you and the CPython team have the same idea and decide to clean up exception references at the end of the except block:
At the end of the except block, CPython will try to delete the name e that you have deleted! To solve this problem, CPython assigns e = None before deleting e to ensure that e exists.
The above python tracking except information method is all the content shared by the editor, I hope to give you a reference.
Recommended Posts