Python Module Tutorial - atexit

Last updated on  Feb 20, 2023  in  Python Programming - Beginner Level  by  Amo Chen  ‐ 3 min read

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.

Requirements

  • Python 3.10

Exit handlers

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

Execution sequence

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:

  1. Signal killed not handled by the program
  2. When a serious internal error occurs in Python, such as a bug in Python itself.
  3. When calling os._exit()

For example:

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.

References

https://docs.python.org/3/library/atexit.html