2017-01-29 2 views
0

Python Multiprocessing Pool haben ein unterschiedliches Verhalten zwischen Linux und Windows. Wenn Sie Method Map nach Anzahl der Worker ausführen, wird in Linux der Prozess für den Bereich der spezifischen Funktion, die Sie als Parameter angegeben haben, ausgeführt. In Windows wird jedoch jeder Worker im Bereich des übergeordneten Prozesses ausgeführt und verwendet erneut Code dass es nicht sein sollte.Python Multiprocessing Pool seltsames Verhalten in Windows

Zum Beispiel: (Der Kolben ist es nur für sie ähnlich wie mein Code zu machen)

from multiprocessing import Pool, Event 
from flask import Flask 

print(">>> This code running for every each worker") 

app = Flask(__name__) 

terminating = None 


def f(**kwargs): 
    print("f()") 
    x = kwargs.pop("x", 1) 
    print(x * x) 
    return x * x 


def worker_warpper(arg): 
    func, kwargs = arg 
    return func(**kwargs) 


def initializer(terminating_): 
    global terminating 
    terminating = terminating_ 


@app.route('/check', methods=['GET']) 
def check(): 
    with Pool(processes=3) as pool: 
     ls = [(f, {"x": 2}), (f, {"x": 5}), (f, {"x": 6})] 
     pool_map = pool.map(worker_warpper, ls) 
    return "Finished" 


if __name__ == "__main__": 
    print("Listening...") 
    app.run(port=5151, host='0.0.0.0') 

Dieser Teil des Codes der Funktion „f“ (nur Funktion „f“) 3-mal laufen bei 3 werden sollte unterschiedlicher Prozess parallel.

Aber es läuft der Druck an der Spitze wieder. (Es ist nicht gerade für jeden Prozess wieder - aber es ist Beziehung zwischen der Anzahl der Male an der Spitze „f“ und die Nummer des Drucks läuft wieder laufen)

print(">>> This code running for every each worker")

Nur in Windows, in Linux läuft nur "f" wieder.

Ausgang: (Linux)

>>> This code running for new worker (not all of the workers) 
Listening 
... 
* Running on http://0.0.0.0:5151/ (Press CTRL+C to quit) 
f() 
4 
f() 
25 
f() 
36 
127.0.0.1 - - 

[29/Jan/2017 11:46:26] "GET /check HTTP/1.1" 200 - 

Ausgang: (Windows)

>>> This code running for new worker (not all of the workers) 
Listening 
... 
* Running on http://0.0.0.0:5151/ (Press CTRL+C to quit) 
>>> This code running for new worker (not all of the workers) 
f() 
4 
f() 
25 
f() 
36 
127.0.0.1 - - 

[29/Jan/2017 11:46:26] "GET /check HTTP/1.1" 200 - 

Warum gibt es unterschiedliche Verhalten zwischen Linux und Windows? Und was kann ich dagegen tun?

Wenn es nicht klar ist, sag es mir und ich werde es anders versuchen.

Danke!

Antwort

1

Der Unterschied zwischen Windows und Linux ist die Art, wie ein untergeordneter Prozess gestartet wird. Unter Linux werden untergeordnete Prozesse unter Verwendung von fork() gestartet: Der neue Prozess startet im gleichen Zustand wie der übergeordnete Prozess: Der Python-Code wird bereits interpretiert und erhält eine Kopie des Speichers des übergeordneten Prozesses.

Unter Windows ist das ganz anders: Prozesse sind spawn ed: ein neuer Python-Interpreter wird gestartet, der wiederum die Python-Datei analysiert und ausführt. Deshalb wird Ihr print Prozess oben erneut ausgeführt.

Für Details siehe the docs about fork vs. spawn.

Eine häufige Falle ist die if __name__ == '__main__' unten zu vermeiden. Aber da Sie dies bereits in Ihrem Code haben, sind Sie dem "sicheren Code" ziemlich nahe.

Was kann ich dagegen tun?

Sie können Threading anstelle von Multithreading verwenden. Wenn Sie einen neuen Thread starten, verwendet der neue Thread denselben Speicherplatz wie der übergeordnete Thread. Nachteil ist, dass Sie nur einen CPU-Kern globalen Interpreter Lock wegen Pythons“nutzen können.

Details siehe this discussion

Verwandte Themen