Kontextmanager und Pools für mehrere Prozesse

Angenommen, Sie verwenden einemultiprocessing.Pool Objekt, und Sie verwenden dieinitializer Einstellung des Konstruktors zur Übergabe einer Initialisierungsfunktion, die dann eine Ressource im globalen Namespace erstellt. Angenommen, die Ressource verfügt über einen Kontextmanager. Wie würden Sie mit dem Lebenszyklus der kontextverwalteten Ressource umgehen, vorausgesetzt, sie muss den gesamten Prozess überleben, aber am Ende ordnungsgemäß bereinigt werden?

Bisher habe ich etwas in der Art:

resource_cm = None
resource = None


def _worker_init(args):
    global resource
    resource_cm = open_resource(args)
    resource = resource_cm.__enter__()

Ab hier können die Poolprozesse die Ressource nutzen. So weit, ist es gut. Aber das Aufräumen ist etwas kniffliger, da diemultiprocessing.Pool Klasse bietet keinedestructor oderdeinitializer Streit.

Eine meiner Ideen ist die Verwendung desatexit Modul, und registrieren Sie die Bereinigung im Initialisierer. Etwas wie das:

def _worker_init(args):
    global resource
    resource_cm = open_resource(args)
    resource = resource_cm.__enter__()

    def _clean_up():
        resource_cm.__exit__()

    import atexit
    atexit.register(_clean_up)

Ist das ein guter Ansatz? Gibt es einen einfacheren Weg, dies zu tun?

BEARBEITEN:atexit scheint nicht zu funktionieren. Zumindest nicht so, wie ich es oben benutze, daher habe ich derzeit noch keine Lösung für dieses Problem.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage