2012-03-30 3 views
1

Ich schaute in den Multiprocessing.Pool für Arbeiter, versuchen, Arbeiter mit einem Zustand zu initialisieren. Der Pool kann aufrufbar initialisiert werden, es wird jedoch kein Verweis auf den initialisierten Worker übergeben. Die wenigen Beispiele, die ich gesehen habe, verwenden sie als globale Variablen, was wirklich eklig erscheint.Verwendung von initialisieren in Python Multiprocessing-Worker-Pool

Gibt es eine gute Möglichkeit, Arbeiterstatus mit Multiprocessing.Pool zu initialisieren?

Edit: Ein Beispiel:

Ich habe Arbeiter, von denen jeder ein wenig relativ teuer Initialisierung tun (Bindung an eine Steckdose), das will ich nicht jedes Mal zu tun haben. Ich könnte meine Sockets von Hand initialisieren und sie dann weitergeben, wenn ich Arbeit zuweisen würde, aber das Teilen von Dateideskriptoren über Prozesse hinweg ist kompliziert, wenn nicht unmöglich. Ich müsste also jedes Mal initialisieren und binden, wenn ich eine Anfrage bearbeiten wollte.

+1

Ich bin ein wenig unklar, warum Ihre Initialisiererfunktion einen Verweis auf den Arbeiter benötigt, vielleicht könnten Sie ein etwas konkreteres, aber minimales Beispiel dafür liefern, was Sie zu tun versuchen. – mgilson

+0

Sie wissen, dass es keine Möglichkeit gibt zu sagen, * welchem ​​* Arbeiter ein bestimmter Funktionsaufruf zugewiesen wird? Warum also nicht einfach diesen Zustand in die Funktionsargumente aufnehmen? –

Antwort

1

Technisch gesehen wäre es das Richtige, das Ergebnis der Initialisierungsfunktion als Argument für jede vom Worker ausgeführte Funktion zu übergeben.

Es ist auch wahr, dass in diesem Kontext gut und sicher ist, globale Variablen zu haben, da sie durch die Konstruktion dazu führen, dass private Objekte in den getrennten Bereichen verschiedener Prozesse leben.

Mein allgemeiner Vorschlag ist, Funktionen mit einem gesunden reentrant-Programmierstil zu erstellen und globale Variablen zuzulassen, während die multiprocessing-Funktionalität ausgenutzt wird.

Ihr Beispiel zu halten, wird die folgende send Funktion erfordert einigen Kontext (in diesem Fall eine Buchse):

def send(socket, data): 
    pass # ... your code here 
    return dust 

Der Initialisierungscode und die Code-Basis durch den Arbeiter ausgeführt wird auf globale Variablen verlassen Bequemlichkeit.

socket = None 
def init(address, port): 
    global socket 
    socket = magic(address, port) 

def job(data): 
    global socket 
    assert socket is not None 
    return send(socket, data) 

pool = multithreading.Pool(N, init, [address, port]) 
pool.map(job, ['foo', 'bar', 'baz']) 

es auf diese Weise durch die Codierung es einfach und natürlich wird es zu testen, ohne Multiprozessing. Sie können sich Ihren globalen Zustand als eine vollkommen sichere Kontextkapsel vorstellen.

Als zusätzlichen Punkt der Bequemlichkeit, bedenken Sie, dass multiprocessing ist nicht sehr gut senden komplexe Daten (z. B. Rückrufe). Der beste Ansatz besteht darin, einfache Daten (Strings, Listen, Wörterbücher, collections.namedtuple ...) zu senden und die komplexen Datenstrukturen auf der Arbeiterseite zu rekonstruieren (mithilfe der Initialisierungsfunktion).