Forum: PC-Programmierung Python3/PyQt5/Windows - bei multiprocessing wir die gui mehrfach erzeugt


von Kaj G. (Firma: RUB) (bloody)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich brauch mal wieder eure Hilfe :-/

Ich arbeite gerade an einem Pythonprojekt, verwendet wird Python 3.4.3 
so wie PyQt5, jeweils in der 64bit version. Das Executable wird mit 
cx-freeze erstellt. Ein Executable ist notwendig, da nicht überall 
Python und PyQt installiert werden soll!

Um das Problem für euch besser greifbar zu machen, habe ich mal ein 
minimal Beispiel angehangen.

Das Beispiel ist eine einfache GUI mit 2 Knöpfen, der Eine startet 3 
Prozesse (die in diesem Beispiel nichts machen außer 30 sekunden 
schlafen), der andere Knopf beendet die Prozesse und schließt die GUI.
Ich verwende hier multiprocessing, und kein threading!

Das Problem:
Unter Windows werden nicht die Prozesse gestartet, dafür wird die GUI 
multiple male neu erzeugt. Unter Linux lässt sich dieses Verhalten 
reproduzieren, wenn man die standard methode zum erzeugen von prozessen 
auf 'spawn' stellt, 'spawn' ist die standard-methode unter windows, 
'fork' kann windows nicht. Nutzt man unter Linux 'fork' als 
standard-methode, so tritt dieses verhalten nicht auf. Das Beispiel ist 
so angepasst, dass auch unter Linux 'spawn' als standard-methode genutzt 
wird, zu finden in main.py
1
MP.set_start_method('spawn')

Das Problem tritt nur auf, wenn man das Executable nutzt, führt man 
das script direkt aus, so tritt das problem nicht auf.

Das Beispiel enthält ein setup-script um das executable zu erzeugen
1
setup.py build
Das script erzeugt einen Ordner namens 'build', dort ist das executable 
zu finden.

Das verhalten kann ich unter Linux (Kernel 4.2) sowie unter Windows 7 
und Windows 10 reproduzieren.

Habt ihr eine Idee weshabl die GUI bei drücken des Knopfes mehrfach 
erzeugt wird, und wie man das löst? :-/

Grüße

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Moin,

ich werde wohl erstmal, als Würg-A-Round, die Teile, die als extra 
Prozess laufen sollen, in seperate executables packen, und diese dann 
über das subprocess-Modul starten.
Ist keine Lösung, aber wenn das erstmal so funktioniert kann ich mich 
erstmal wieder auf die weitere Funktionalität konzentrieren.

Wäre mir trotzdem lieb, wenn man dieses Problem irgendwie lösen könnte. 
Also "richtig" lösen, ganz ohne würg-a-rounds :)

Grüße

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?


von Lars R. (lrs)


Lesenswert?

Für Threads verwende ich in diesem Fall QThread. Zusammen mit python 
"executables" habe ich das noch nicht probiert.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Lars R. schrieb:
> Für Threads verwende ich in diesem Fall QThread.
Ich rede hier aber von Prozessen nicht von Threads :)
Abgesehen davon sehe ich in QThreads keinen grossartigen vorteil, 
gegenueber dem standard threading-modul von Python.


Ich hab das ganze jetzt mal ausprobiert. Wenn man das main-Modul 
(main.py) so umschreibt:
1
import multiprocessing as MP
2
3
...
4
5
if __name__ == '__main__':
6
  MP.freeze_support()
7
  main()
tritt das Problem nicht mehr auf.

Zusammenfassung:
Das Problem tritt nur unter Windows auf, und nur dann, wenn man das 
ganze als exe-Datei baut!
Dieser Fix funktioniert nur unter Windows.
Nutzt man unter Linux die Spawn-Methode (um das Problem dort zu 
reproduzieren), so hilft dieser fix nicht ! Unter Linux sollte man bei 
der standard Methode 'fork' bleiben. Mit 'fork' tritt dieses Problem 
nicht auf, auch dann nicht, wenn man das ganze als executable baut.

Gruesse

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.