2017-07-14 1 views
4

Wie wir alle wissen, müssen wir den main() schützen, wenn Code mit multiprocessing in Python läuft if __name__ == '__main__' verwenden.Behelfslösung für __name mit __ == ‚__ main__‘ in Python Multiprocessing

Ich verstehe, dass dies in einigen Fällen notwendig ist, den Zugriff auf Funktionen in der Haupt definiert zu geben, aber ich verstehe nicht, warum dies in diesem Fall notwendig ist:

file2.py

import numpy as np 
from multiprocessing import Pool 
class Something(object): 
    def get_image(self): 
     return np.random.rand(64,64) 

    def mp(self): 
     image = self.get_image() 
     p = Pool(2) 
     res1 = p.apply_async(np.sum, (image,)) 
     res2 = p.apply_async(np.mean, (image,)) 
     print(res1.get()) 
     print(res2.get()) 
     p.close() 
     p.join() 

main.py

Alle für Something erforderlichen Funktionen oder Importe sind Teil von file2.py. Warum muss der Unterprozess die main.py erneut ausführen?

Ich denke, die __name__ Lösung ist nicht sehr nett, da dies verhindert, dass ich den Code von file2.py verteile, da ich nicht sicherstellen kann, dass sie ihre Haupt schützen. Gibt es keine Problemumgehung für Windows? Wie sind Pakete zu lösen, dass -

bearbeiten (da ich nie ein Problem nicht schützen mein Haupt mit jedem Paket begegnet sind sie mit Multiprozessing einfach nicht?): Ich weiß, dass dies wegen der fork() ist nicht implementiert in Windows. Ich frage mich, ob es ein Hack ist der Dolmetscher bei file2.py statt main.py beginnen zu lassen, wie ich sicher sein kann, dass file2.py autark ist

+3

Der 'if __name__ == '__main __'' Hack ist nur unter Windows notwendig, da diese Plattform kein 'fork()' hat. Wenn Sie _jemand_ anderes Betriebssystem wählen, brauchen Sie es nicht. –

+0

OP, nur um zu bestätigen, Sie _ sind _ auf Windows, richtig? –

+1

Wenn ich Sie richtig verstanden habe, schreiben Sie 'file2.py' als Bibliothek, und Sie möchten Benutzercode wie' main.py' unterstützen (der möglicherweise in Zukunft von einer anderen Person geschrieben wird). Leider glaube ich nicht, dass es einen Weg gibt, Ihre Benutzer vor den Anforderungen von Multiprocessing zu schützen. Sie müssen wahrscheinlich nur dokumentieren, dass Ihr Modul Skript-Code benötigt, der in 'if __name__ ==" __main __ "' Blöcke gesetzt wird, so dass nichts ausgeführt wird, wenn das Modul importiert wird. – Blckknght

Antwort

1

Das Hauptmodul importiert wird (aber mit __name__ != '__main__' da Windows versucht, ein Forking-ähnliches Verhalten zu simulieren, auf Ein System, das keine Verzweigung hat multiprocessing hat keine Möglichkeit zu wissen, dass Sie nichts Wichtiges in Ihrem Hauptmodul getan haben, daher wird der Import "nur für den Fall" durchgeführt, um eine Umgebung ähnlich der Ihres Hauptprozesses zu erstellen Wenn dies nicht der Fall ist, werden möglicherweise alle möglichen Dinge, die durch Nebeneffekte in main auftreten (z. B. Importe, Konfigurationsaufrufe mit anhaltenden Nebenwirkungen usw.), in den untergeordneten Prozessen möglicherweise nicht ordnungsgemäß ausgeführt

Als solche, wenn sie nicht ihre __main__ schützen, ist der Code nicht Multiprocessing sicher (noch ist es unittest sicher, Import sicher, etc.). Die Schutzhülle if __name__ == '__main__': sollte Teil aller korrekten Hauptmodule sein. Fahren Sie fort und verteilen Sie es mit einem Hinweis, dass Sie einen Multiprozessor-sicheren Hauptmodulschutz benötigen.

4

Wenn die „Spawn“ mit Start-Methode, sind neue Prozesse Python Dolmetscher, die von Null angefangen. Es ist nicht möglich, dass die neuen Python-Interpreter in den Subprozessen herausfinden, welche Module importiert werden müssen, damit sie das Hauptmodul erneut importieren, was wiederum alles andere importiert. Dies bedeutet, dass es möglich sein muss, das Hauptmodul ohne irgendwelche Nebenwirkungen zu importieren.

Wenn Sie auf einer anderen Plattform als Windows arbeiten, können Sie stattdessen die Startmethode "fork" verwenden, und Sie haben dieses Problem nicht.

Das sagte, was ist los mit if __name__ == "__main__": verwenden? Es hat viele zusätzliche Vorteile, z.B. Dokumentations-Tools werden in der Lage sein, Ihr Hauptmodul zu verarbeiten, und Unit-Tests sind einfacher usw., also sollten Sie es auf jeden Fall verwenden.

1

Die if __name__ == '__main__' wird für Windows benötigt, da Windows keine "fork" -Option für Prozesse hat.

In Linux, zum Beispiel, können Sie den Prozess fork, so wird der übergeordnete Prozess kopiert und die Kopie wird das Kind Prozess werden (und es wird die bereits importierten Code haben Zugriff auf Sie im übergeordneten Prozess geladen hatte)

Da Sie in Windows nicht forkieren können, importiert Python einfach den gesamten Code, der vom übergeordneten Prozess im untergeordneten Prozess importiert wurde. Dies erzeugt einen ähnlichen Effekt, aber wenn Sie nicht den __name__ Trick ausführen, führt dieser Import Ihren Code erneut im untergeordneten Prozess aus (und dadurch wird es zum Erstellen eines eigenen untergeordneten Elements und so weiter).

so auch in Ihrem Beispiel main.py wird wieder importiert werden (da alle Dateien erneut importiert werden). Python kann nicht erraten, welches spezifische Python-Skript der Kindprozess importieren soll.

FYI gibt es weitere Einschränkungen Sie sollten wie mit Globals darüber im Klaren sein, kann man darüber lesen Sie hier https://docs.python.org/2/library/multiprocessing.html#windows