Frage

Ich versuche atexit in einem Process zu verwenden, aber leider scheint es nicht zu arbeiten. Hier einige Beispiel-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()

Die Ausgabe dieses Codes ist:

DEBUG:root:Main process started
DEBUG:root:W-1 Started
DEBUG:root:W-2 Started
DEBUG:root:Main process terminated

Ich würde erwarten, dass die W.run.log_terminate() genannt werden würden, wenn a.terminate() und b.terminate() genannt werden, und die Ausgabe etwas sein likeso (Hervorhebung hinzugefügt):

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

Warum ist das nicht funktioniert, und gibt es eine bessere Art und Weise eine Nachricht zu protokollieren (aus dem Process Kontext), wenn ein Process beendet wird?

Vielen Dank für Ihre Eingabe - es ist sehr zu schätzen

.

Lösung

EDIT: Basierend auf Lösung von Alex Martelli vorgeschlagen, wie die folgenden Werke zu erwarten:

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()

Es lohnt sich, den folgenden Kommentar in der atexit Dokumentation zu beachten:

. Hinweis: die über dieses Modul registrierten Funktionen werden nicht aufgerufen, wenn das Programm durch ein Signal getötet wird, wenn ein Python schwerwiegende internen Fehler erkannt werden, oder wenn os._exit () aufgerufen wird
War es hilfreich?

Lösung

Wie die docs sagen,

  

Auf Unix dies geschieht, um die SIGTERM mit   Signal; unter Windows TerminateProcess ()   wird genutzt. Beachten Sie, dass Exit-Handler und   schließlich Klauseln etc., werden nicht   ausgeführt wird.

Wenn Sie auf Unix sind, sollten Sie in der Lage abfangen SIGTERM sein mit

scroll top