Python 3: Monkey-patchen Code kann nicht durch Multiprocessing wieder importiert werden

8

In Kürze

Wie kann ich Modul A von Modul B kopieren, wenn die Funktionen von Modul A importiert werden sollen, damit ich die Funktionen von Modul A mit dem% standard Bibliothekspaket multiprocessing ausführen kann?

Hintergrund

Ein Client hat einen Hotfix angefordert, der auf keinen unserer anderen Clients anwendbar ist. Deshalb habe ich einen neuen Zweig erstellt und ein separates Modul geschrieben, damit die Änderungen in der Master-Verzweigung einfach zusammengeführt werden können. Um die Abwärtskompatibilität des Clients mit dem Verhalten vor Hotfix zu gewährleisten, habe ich den Hotfix als konfigurierbare Einstellung in der App implementiert. Daher wollte ich meinen alten Code nicht ersetzen - füge ihn einfach ein, wenn die Einstellung aktiviert war. Ich tat dies durch Affen flicken .

Code-Struktur

Das Modul __main__ liest die Konfigurationsdatei ein. Wenn die Konfiguration den Wechsel des Hotfixes aktiviert, patcht __main__ mein engine -Modul, indem sie einige Funktionen durch den im hotfix -Modul definierten Code ersetzt - im Wesentlichen ist die zu ersetzende Funktion das Schlüsselfunktion zu einer Maximierungsfunktion . Das Modul engine lädt später einen Pool von multiprocessing Arbeitern.

Das Problem

Sobald ein multiprocessing worker gestartet wird, macht die erste Sache multiprocessing es erneut importiert * das engine modul und sucht nach der Schlüsselfunktion, die __main__ versucht hat zu ersetzen (dann multiprocessing übergibt die Kontrolle an meinen Code und der Maximierungsalgorithmus beginnt). Da engine durch einen brandneuen Prozess neu importiert wird und der neue Prozess __main__ (wo die Konfigurationsdatei gelesen wird) nicht erneut ausführt, weil dies eine Endlosschleife verursachen würde, weiß es nicht, Affe-Patch engine .

Die Frage

Wie kann ich Modularität in meinem Code beibehalten (d. h. den Hotfix-Code in einem separaten Modul beibehalten) und trotzdem das Paket multiprocessing von Python nutzen?

* Beachten Sie, dass mein Code unter Windows (für meinen Client) und Unix (für meine Gesundheit ...) funktionieren muss.

    
wkschwartz 14.09.2012, 15:25
quelle

3 Antworten

1

Das hört sich nach einem Ort an, an dem Affe-Flicken einfach nicht funktioniert. Es ist einfacher, die betreffenden Funktionen einfach in separate Module zu extrahieren und sie von dort zu importieren. Vielleicht können Sie eine Konfigurationseinstellung haben, wo Sie sie importieren können.

Eine andere Möglichkeit, dies zu modularisieren, ist die Verwendung einer Art von Komponentenarchitektur, wie ZCA . Diese letzte Option ist, was ich würde gehen, aber das ist, weil ich daran gewöhnt bin, so gibt es kein extra Lernen für mich.

    
Lennart Regebro 15.09.2012 06:12
quelle
1

Damit es unter einem UNIX / Linux-Betriebssystem mit fork() funktioniert, müssen Sie nichts Spezielles tun, da der neue Prozess Zugriff auf die gleichen (affe-gepatchten) Klassen wie die Eltern hat.

>

Damit es unter Windows funktioniert, muss Ihr __main__ -Modul die Konfiguration beim Import lesen (den Aufruf read_config / patch_engine im globalen Gültigkeitsbereich), aber das Multiprocessing (Engine-Ausführung) in einem if __name__ == '__main__' Wache.

Dann wird der read-config-Code immer dann ausgeführt, wenn __main__ importiert wird (entweder von der Befehlszeile oder von multiprocessing reimport), aber der if __name__ == '__main__' -Code wird nur ausgeführt, wenn Ihr Skript aufgerufen wird die Befehlszeile (da __main__ im untergeordneten Prozess unter einem anderen Namen erneut importiert wird).

    
nneonneo 17.09.2012 18:51
quelle
0

Klingt so, als müssten Sie engine.py modifizieren, um eine Konfigurationsdatei zu überprüfen und sie bei Bedarf selbst patchen zu lassen.

Um sowohl an Unix als auch an Windows zu arbeiten, kann engine eine globale Variable CONFIG_DONE behalten, um zu entscheiden, ob sie erneut nach der Konfigurationsdatei suchen muss.

    
Ethan Furman 14.09.2012 22:04
quelle