2015-12-29 3 views
5

Ich habe einige Teilprozesse (mit Multiprocessing) und wenn sie aufhören, muss jeder von ihnen einige letzte Arbeit erledigen. Etwas wie das folgende, das nicht funktionierte, aber ...Wie "ATEXIT" -Funktion in Python Multiprocessing-Subprozess registrieren?

import multiprocessing 
import atexit 

def final(): 
    print "final work" 

def worker(): 
    print 'Doing some work' 
    atexit.register(final) 

if __name__ == '__main__': 
    p = multiprocessing.Process(target=worker) 
    p.start() 
    p.join() 

So wie konnte ich das tun?

+0

Überprüfen Sie http://stackoverflow.com/questions/1231599/python-multiprocessing-exit-elegantly-how, was ähnlich zu dem ist, was Sie erreichen möchten. –

Antwort

1

Prozesse, die über Multiprocessing gestartet wurden, werden nicht normal beendet und atexit Funktionen werden nie aufgerufen. Sie müssen Bereinigung Zeug manuell über einen try/finally-Block, zum Beispiel laufen:

def worker(): 
    try: 
     print('Doing some work') 
    finally: 
     final() 

Oder, wenn Sie wirklich verwenden möchten atexit (siehe unten für die Nachteile):

def worker(): 
    try: 
     print('Doing some work') 
    finally: 
     atexit._run_exitfuncs() 

Warum werden Subprozesse nicht normal beendet?

Technisch, weil they quit via os._exit(), überspringt alle Aufräumarbeiten (einschließlich atexit Funktionen, __del__() und weakref Finalisierer).

Der Grund für diese Entscheidung ist, dass Cleanup-Sachen riskieren, zur falschen Zeit im falschen Prozess ausgeführt zu werden. Der Großteil des Codes, der atexit (oder andere Mechanismen) verwendet, erwartet, dass der Code nur einmal ausgeführt wird und nur wenn der Haupt-Interpreter beendet wird (zum Beispiel kann man atexit verwenden, um ein temporäres Verzeichnis zu entfernen). Durch Ausführen von atexit Funktionen jedes Mal, wenn ein Subprozess beendet wird, brechen Sie diese Erwartung und es können schlimme Dinge passieren.

Also, auch wenn Sie atexit Funktionen über atexit._run_exitfuncs() ausführen können, vermeiden, so zu tun, weil sowohl die Funktion nicht dokumentiert ist und weil Sie nicht der einzige Benutzer von atexit (anderen Bibliotheken von Drittanbietern kann es verwenden können, und Sie können einführen Fehler in ihrem Code).

+0

Das war eine absurde Entscheidung. atexit-Funktionen erwarten nicht, dass sie von "main" aufgerufen werden. Sie erwarten, in dem Prozess, in dem sie registriert wurden, aufgerufen zu werden. also muss atexit lediglich die pid der registrierung speichern, um zu wissen, ob sie angerufen werden können. Alle Module, die atexit verwenden, werden jetzt in einem Multiprocessing-Job unbrauchbar ... zwingt mich stattdessen, Popen zu verwenden und ihren eigenen Zustand zu pikken. Ich habe tatsächlich Multiprozessing gegabelt, nur um die richtigen Aufräumarbeiten wieder einzusetzen. –

Verwandte Themen