Es tut mir leid, dass ich den Fehler nicht mit einem einfacheren Beispiel reproduzieren kann und mein Code zu kompliziert ist, um ihn zu veröffentlichen. Wenn ich das Programm in der IPython-Shell anstelle des regulären Python ausführe, funktionieren die Dinge gut.
Ich habe einige frühere Hinweise zu diesem Problem nachgeschlagen. Sie wurden alle durch die Verwendung von pool zum Aufrufen einer Funktion verursacht, die innerhalb einer Klassenfunktion definiert wurde. Dies ist aber bei mir nicht der Fall.
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 313, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
Ich würde mich über jede Hilfe freuen.
Update : Die Funktion, die ich auswähle, wird auf der obersten Ebene des Moduls definiert. Es wird jedoch eine Funktion aufgerufen, die eine verschachtelte Funktion enthält. dh f()
ruft g()
Anrufe auf, h()
die eine verschachtelte Funktion haben i()
, und ich rufe an pool.apply_async(f)
. f()
, g()
, h()
Sind alle auf der obersten Ebene definiert. Ich habe ein einfacheres Beispiel mit diesem Muster versucht und es funktioniert jedoch.
dill
und zu lesenpathos
. Ich habe jedoch kein Glück mit einer der Lösungen bei der Arbeit mit vtkobjects :( Hat es jemand geschafft, Python-Code in paralleler Verarbeitung von vtkPolyData auszuführen?Antworten:
Hier ist eine Liste, was eingelegt werden kann . Insbesondere können Funktionen nur ausgewählt werden, wenn sie auf der obersten Ebene eines Moduls definiert sind.
Dieser Code:
ergibt einen Fehler, der fast identisch mit dem von Ihnen geposteten ist:
Das Problem ist, dass
pool
alle Methoden a verwendenmp.SimpleQueue
, um Aufgaben an die Arbeitsprozesse zu übergeben. Alles, was durch das geht,mp.SimpleQueue
muss auswählbar sein undfoo.work
ist nicht auswählbar, da es nicht auf der obersten Ebene des Moduls definiert ist.Sie kann behoben werden, indem auf der obersten Ebene eine Funktion definiert wird, die Folgendes aufruft
foo.work()
:Beachten Sie, dass dies
foo
auswählbar ist, daFoo
es auf der obersten Ebene definiert undfoo.__dict__
auswählbar ist.quelle
pool = Pool()
Zeile hier ) vorausgehen muss . Ich habe das nicht erwartet, und dies könnte der Grund sein, warum das Problem von OP weiterhin bestand.functool.partial
auf eine Funktion der obersten Ebene auch beizbar ist, selbst wenn es in einer anderen Funktion definiert ist.Ich würde
pathos.multiprocesssing
stattdessen verwendenmultiprocessing
.pathos.multiprocessing
ist ein Fork von ,multiprocessing
dass Anwendungendill
.dill
kann fast alles in Python serialisieren, so dass Sie viel mehr parallel senden können. Derpathos
Fork kann auch direkt mit mehreren Argumentfunktionen arbeiten, wie Sie dies für Klassenmethoden benötigen.Holen Sie sich
pathos
(und wenn Sie möchtendill
) hier: https://github.com/uqfoundationquelle
sudo pip install git+https://github.com/uqfoundation/dill.git@master
undsudo pip install git+https://github.com/uqfoundation/pathos.git@master
sudo
(insbesondere von externen Quellen wie Github). Stattdessen würde ich empfehlen zu laufen:pip install --user git+...
pip install pathos
funktioniert leider nicht und gibt folgende Meldung aus:Could not find a version that satisfies the requirement pp==1.5.7-pathos (from pathos)
pip install pathos
funktioniert jetzt undpathos
ist Python 3-kompatibel.multiprocess
ist ein Fork vonmultiprocessing
wodill
ersetzt hatpickle
an mehreren Stellen im Code ... aber im Wesentlichen, dass es.pathos
Bietet einige zusätzliche API-Ebenenmultiprocess
und zusätzliche Backends. Aber das ist der Kern davon.Wie andere gesagt haben,
multiprocessing
können Python-Objekte nur an Arbeitsprozesse übertragen werden, die eingelegt werden können. Wenn Sie Ihren Code nicht wie von unutbu beschrieben reorganisieren können, können Sie diedill
erweiterten Beiz- / Entpickelfunktionen zum Übertragen von Daten (insbesondere Codedaten) verwenden, wie unten gezeigt.Diese Lösung erfordert nur die Installation
dill
und keine anderen Bibliotheken wie folgtpathos
:quelle
dill
undpathos
Autor ... und obwohl Sie Recht haben, ist es nicht so viel schöner und sauberer und flexibler, es auch zu verwenden,pathos
als in meiner Antwort? Oder vielleicht bin ich ein bisschen voreingenommen ...pathos
zum Zeitpunkt des Schreibens nicht bewusst und wollte eine Lösung vorstellen, die der Antwort sehr nahe kommt. Nachdem ich Ihre Lösung gesehen habe, stimme ich zu, dass dies der richtige Weg ist.Doh… I didn't even think of doing it like that.
dachte: Das war irgendwie cool.for
Schleife gibt. Normalerweise würde eine parallele Routine eine Liste erstellen und eine Liste ohne Schleife zurückgeben.Ich habe festgestellt, dass ich auch genau diese Fehlerausgabe auf einem perfekt funktionierenden Code generieren kann, indem ich versuche, den Profiler darauf zu verwenden.
Beachten Sie, dass dies unter Windows war (wo das Gabeln etwas weniger elegant ist).
Ich lief:
Und festgestellt, dass durch Entfernen der Profilerstellung der Fehler behoben und durch Platzieren der Profilerstellung wiederhergestellt wurde. Hat mich auch verrückt gemacht, weil ich wusste, dass der Code funktioniert hat. Ich überprüfte, ob etwas pool.py aktualisiert hatte ... dann hatte ich ein sinkendes Gefühl und beseitigte die Profilerstellung und das wars.
Hier für die Archive posten, falls jemand anderes darauf stößt.
quelle
pass
war nicht 'pickle'able.Wenn dieses Problem auftritt, besteht
multiprocessing
eine einfache Lösung darin, vonPool
zu zu wechselnThreadPool
. Dies kann ohne Änderung des Codes außer dem Import erfolgen.Dies funktioniert, weil ThreadPool den Speicher mit dem Hauptthread teilt, anstatt einen neuen Prozess zu erstellen. Dies bedeutet, dass kein Beizen erforderlich ist.
Der Nachteil dieser Methode ist, dass Python nicht die beste Sprache für den Umgang mit Threads ist. Es verwendet die sogenannte globale Interpreter-Sperre, um die Thread-Sicherheit zu gewährleisten, was hier einige Anwendungsfälle verlangsamen kann. Wenn Sie jedoch hauptsächlich mit anderen Systemen interagieren (HTTP-Befehle ausführen, mit einer Datenbank sprechen, in Dateisysteme schreiben), ist Ihr Code wahrscheinlich nicht an die CPU gebunden und wird keinen großen Einfluss haben. Tatsächlich habe ich beim Schreiben von HTTP / HTTPS-Benchmarks festgestellt, dass das hier verwendete Thread-Modell weniger Overhead und Verzögerungen aufweist, da der Overhead beim Erstellen neuer Prozesse viel höher ist als der Overhead beim Erstellen neuer Threads.
Wenn Sie also eine Menge Dinge im Python-Benutzerbereich verarbeiten, ist dies möglicherweise nicht die beste Methode.
quelle
Es funktioniert auch für numpy Arrays.
quelle
Dieser Fehler tritt auch auf, wenn Sie eine integrierte Funktion im Modellobjekt haben, die an den asynchronen Job übergeben wurde.
So stellen Sie sicher , die überprüfen Modellobjekte , die vergangen sind , keine eingebauten Funktionen. (In unserem Fall haben wir die
FieldTracker()
Funktion von Django-Modell-Utils innerhalb des Modells verwendet, um ein bestimmtes Feld zu verfolgen). Hier ist der Link zum relevanten GitHub-Problem.quelle
Aufbauend auf der @ rocksportrocker-Lösung wäre es sinnvoll, beim Senden und Empfangen der Ergebnisse Dill zu verwenden.
quelle