I'm trying to use atexit
in a Process
, but unfortunately it doesn't seem to work. Here's some example code:
import time import atexit import logging import multiprocessing logging.basicConfig(level=logging.DEBUG) class W(multiprocessing.Process): def run(self): logging.debug("%s Started" % self.name) @atexit.register def log_terminate(): # ever called? logging.debug("%s Terminated!" % self.name) while True: time.sleep(10) @atexit.register def log_exit(): logging.debug("Main process terminated") logging.debug("Main process started") a = W() b = W() a.start() b.start() time.sleep(1) a.terminate() b.terminate()
The output of this code is:
DEBUG:root:Main process started DEBUG:root:W-1 Started DEBUG:root:W-2 Started DEBUG:root:Main process terminated
I would expect that the W.run.log_terminate()
would be called when a.terminate()
and b.terminate()
are called, and the output to be something likeso (emphasis added)!:
DEBUG:root:Main process started DEBUG:root:W-1 Started DEBUG:root:W-2 Started DEBUG:root:W-1 Terminated! DEBUG:root:W-2 Terminated! DEBUG:root:Main process terminated
Why isn't this working, and is there a better way to log a message (from the Process
context) when a Process
is terminated?
Thank you for your input - it's much appreciated.
EDIT: Based on solution suggested by Alex Martelli, the following works as expected:
import sys import time import atexit import signal import logging import multiprocessing logging.basicConfig(level=logging.DEBUG) class W(multiprocessing.Process): def run(self): logging.debug("%s Started" % self.name) def log_terminate(num, frame): logging.debug("%s Terminated" % self.name) sys.exit() signal.signal(signal.SIGTERM, log_terminate) while True: time.sleep(10) @atexit.register def log_exit(): logging.debug("Main process terminated") logging.debug("Main process started") a = W() b = W() a.start() b.start() time.sleep(1) a.terminate() b.terminate()
It's worthwhile to note the following comment in the atexit
documentation:
Note: the functions registered via this module are not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called.
As the docs say,
On Unix this is done using the SIGTERM signal; on Windows TerminateProcess() is used. Note that exit handlers and finally clauses, etc., will not be executed.
If you're on Unix, you should be able intercept SIGTERM
with signal, and perform whatever "termination activities" you need; however, I don't know of a cross-platform solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With