Wäre es möglich, einen Python-Pool zu erstellen, der nicht dämonisch ist? Ich möchte, dass ein Pool eine Funktion aufrufen kann, in der sich ein anderer Pool befindet.
Ich möchte dies, weil Deamon-Prozesse keinen Prozess erstellen können. Insbesondere wird der Fehler verursacht:
AssertionError: daemonic processes are not allowed to have children
Stellen Sie sich zum Beispiel das Szenario vor, in dem function_a
ein Pool ausgeführt wird, in function_b
dem ein Pool ausgeführt wird function_c
. Diese Funktionskette schlägt fehl, da function_b
sie in einem Daemon-Prozess ausgeführt wird und Daemon-Prozesse keine Prozesse erstellen können.
I want a pool to be able to call a function that has another pool inside
und wie sich dies auf die Tatsache auswirkt, dass die Mitarbeiter dämonisiert sind.AssertionError: daemonic processes are not allowed to have children
Antworten:
Die
multiprocessing.pool.Pool
Klasse erstellt die Worker-Prozesse in ihrer__init__
Methode, macht sie dämonisch und startet sie. Es ist nicht möglich, ihrdaemon
AttributFalse
vor dem Start zurückzusetzen (und danach ist dies nicht mehr zulässig). Sie können jedoch Ihre eigene Unterklasse vonmultiprocesing.pool.Pool
(multiprocessing.Pool
ist nur eine Wrapper-Funktion) erstellen und Ihre eigene Unterklasse ersetzenmultiprocessing.Process
, die immer nicht dämonisch ist und für die Worker-Prozesse verwendet wird.Hier ist ein vollständiges Beispiel dafür. Die wichtigen Teile sind die beiden Klassen
NoDaemonProcess
undMyPool
oben und am Endepool.close()
undpool.join()
auf IhrerMyPool
Instanz aufzurufen .quelle
multiprocessing.freeze_support()
MyPool
anstelle der StandardeinstellungPool
? Mit anderen Worten, welche Kosten zahle ich im Austausch für die Flexibilität beim Starten von untergeordneten Prozessen? (Wenn es keine KostenPool
gäbe, hätte der Standard vermutlich nicht-dämonische Prozesse verwendet).Pool
Klasse umfassend überarbeitet, esProcess
handelt sich also nicht mehr um ein einfaches Attribut, sondern um eine Methode, die die Prozessinstanz zurückgibt, die sie aus einem Kontext erhält . Ich habe versucht, diese Methode zu überschreiben, um eineNoDaemonPool
Instanz zurückzugeben. Dies führt jedoch zu einer Ausnahme,AssertionError: daemonic processes are not allowed to have children
wenn der Pool verwendet wird.Ich musste in Python 3.7 einen nicht-dämonischen Pool verwenden und passte schließlich den in der akzeptierten Antwort angegebenen Code an. Unten befindet sich das Snippet, das den nicht-dämonischen Pool erstellt:
Da die aktuelle Implementierung von
multiprocessing
umfassend überarbeitet wurde, um auf Kontexten zu basieren, müssen wir eineNoDaemonContext
Klasse bereitstellen , die unserNoDaemonProcess
as-Attribut hat.MyPool
verwendet dann diesen Kontext anstelle des Standardkontexts.Trotzdem sollte ich warnen, dass dieser Ansatz mindestens zwei Einschränkungen aufweist:
multiprocessing
Pakets ab und kann daher jederzeit unterbrochen werden.multiprocessing
es so schwierig war, nicht-dämonische Prozesse zu verwenden, von denen viele hier erklärt werden . Das überzeugendste ist meiner Meinung nach:quelle
AttributeError: module 'multiprocessing' has no attribute 'pool'
in Python 3.8.0import multiprocessing.pool
Das Multiprozessor- Modul verfügt über eine schöne Schnittstelle zur Verwendung von Pools mit Prozessen oder Threads. Abhängig von Ihrem aktuellen Anwendungsfall können Sie die Verwendung
multiprocessing.pool.ThreadPool
für Ihren äußeren Pool in Betracht ziehen , was zu Threads (die es ermöglichen, Prozesse von innen heraus zu erzeugen) im Gegensatz zu Prozessen führt.Es könnte durch die GIL beschränkt sein, sondern in meinem speziellen Fall (I getestet beide) , die Startzeit für die Prozesse von den äußeren
Pool
wie geschaffen hier weit überwog mit der LösungThreadPool
.Es ist wirklich einfach zu tauschen
Processes
fürThreads
. Lesen Sie hier oder hier mehr darüber, wie Sie eineThreadPool
Lösung verwenden .quelle
Bei einigen Python-Versionen kann das Ersetzen des Standardpools durch einen benutzerdefinierten Fehler den folgenden Fehler auslösen :
AssertionError: group argument must be None for now
.Hier habe ich eine Lösung gefunden, die helfen kann:
quelle
concurrent.futures.ProcessPoolExecutor
hat diese Einschränkung nicht. Es kann problemlos einen verschachtelten Prozesspool haben:Der obige Demonstrationscode wurde mit Python 3.8 getestet.
Gutschrift: Antwort von jfs
quelle
multiprocessing.Pool
in aProcessPoolExecutor.Pool
ist auch möglich!Das Problem, auf das ich gestoßen bin, war der Versuch, Globals zwischen Modulen zu importieren, was dazu führte, dass die ProcessPool () - Zeile mehrmals ausgewertet wurde.
globals.py
Importieren Sie dann sicher von einer anderen Stelle in Ihrem Code
quelle
Ich habe Leute Umgang mit diesem Problem gesehen durch die Verwendung
celery
‚s Gabelmultiprocessing
genannt Billard (Multiprocessing - Pool - Erweiterungen), die dämonische Prozesse zu laichen Kinder erlaubt. Der Walkaround besteht darin, dasmultiprocessing
Modul einfach zu ersetzen durch:quelle