Python process that is connected will not call atexit

I thought Python processes call their atexit functions when they end. Please note that I am using Python 2.7. Here's a simple example:

from __future__ import print_function
import atexit
from multiprocessing import Process


def test():
    atexit.register(lambda: print("atexit function ran"))

process = Process(target=test)
process.start()
process.join()

      

I expect this to print "atexit function ran", but it doesn't.

Note that this question: A Python process will not invoke atexit in the same way, but it includes Processes that end in a signal, and the answer involves catching that signal. The Processes in this question exit gracefully, so (as far as I can tell, somehow) this question and answer doesn't apply (unless those Processes exit due to a signal somehow?).

+3


source to share


1 answer


I did some research looking at how this is implemented in CPython. This assumes you are on Unix. If you are on Windows, the following may not be valid because the process implementation is different in multiprocessing

.

It turns out to be os._exit()

always called at the end of the process. This, along with the following note from the documentation for atexit , should explain why your lambda is not working.

Note. Functions registered through this module are not called when the program is killed by a signal that is not handled by Python, when Python detects a fatal internal error, or when os._exit () is called.




Here's an excerpt from a class Popen

for CPython 2.7 used for forking processes. Note that the last operator of the forked process is the call os._exit()

.

# Lib/multiprocessing/forking.py

class Popen(object):

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None

        self.pid = os.fork()
        if self.pid == 0:
            if 'random' in sys.modules:
                import random
                random.seed()
            code = process_obj._bootstrap()
            sys.stdout.flush()
            sys.stderr.flush()
            os._exit(code)

      

In Python 3.4, os._exit()

it still exists if you start the markup process, which is the default. But it looks like you can change it, see Contexts and Launch Methods for more information. I haven't tried it, but maybe using the spawn launch method will work? Not available for Python 2.7.

+3


source







All Articles