Recently when I was looking at the source code of Elastic APM agent for Python, I saw that the developers of the project have used the atexit module to close the metrics collect timer before the APM agent shuts down.
Since I am not very familiar with
atexit, I decided to study it in this article.
- Python 3.10
The atexit module defines functions to register and unregister cleanup functions.
The atexit module allows us to register or unregister functions to be executed when the program ends (more strictly, when the Python interpreter ends execution) before. These functions are usually used to perform the final operations, so they are called cleanup functions, such as closing connections, closing files, etc.
For example, the following example will print ‘Goodbye’ when the program ends.
import atexit def main(): for x in range(10): print(x) @atexit.register def print_goodbye(): print('Goodbye') if __name__ == '__main__': main()
The following is the result of the above program, it can be seen that there is no
print('Goodbye') in the
main() function, but the string “Goodbye” is still printed at the end, this is the purpose of the atexit module, allowing the program to execute the specified function before exiting.
0 1 2 3 4 5 6 7 8 9 Goodbye
atexit also supports the registration of multiple functions.
import atexit def A(): print('A') def B(): print('B') def C(): print('C') if __name__ == '__main__': atexit.register(A) atexit.register(B) atexit.register(C)
The execution result as follows:
C B A
If multiple functions are registered, the execution order of the functions will be the reverse of the registration order.
atexit runs these functions in the reverse order in which they were registered; if you register A, B, and C, at interpreter termination time they will be run in the order C, B, A.
Precautions for atexit
When the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when
os._exit() is called, the functions registered via this module will not be triggered.
According to the official document,
atexit cannot be executed in 3 cases:
- Signal killed not handled by the program
- When a serious internal error occurs in Python, such as a bug in Python itself.
- When calling
import atexit import os def A(): print('A') if __name__ == '__main__': atexit.register(A) os._exit(1)
In the above example, the functions registered with atexit will not be executed because
os._exit(1) is used.
When we stop the program below using the command
kill -9 <pid>,
atexit will not be executed either.
import atexit from time import sleep def A(): print('A') if __name__ == '__main__': atexit.register(A) while True: print(1) sleep(10)
That’s a simple explanation of the Python atexit module.