2015-04-10 14 views
7

Ich verwende Qt für die Entwicklung von GUI-Anwendungen.Multiprocessing mit Qt funktioniert in Windows aber nicht Linux

Ich erhalte eine Fehlermeldung, wenn ich versuche QApplicationmultiprocessing mit anderen zu erstellen:

RuntimeError: A QApplication instance already exists

ich ein Hauptfenster haben, die zum Laichen einen neuen Prozess eine Schaltfläche enthält, so dass ich eine neue GUI-Instanz erstellen können. Im Grunde wie folgt aus:

from PySide.QtCore import * 
from PySide.QtGui import * 
import multiprocessing 
import sys 


class MainWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     btn = QPushButton('run new instance') 
     btn.clicked.connect(self.create_daemon) 
     self.setCentralWidget(btn) 

    def create_daemon(self): 
     p = multiprocessing.Process(target=new_window) 
     p.start() 

def new_window(): 
    app=QApplication(sys.argv) 
    ex = MainWindow() 
    ex.show() 
    sys.exit(app.exec_()) 

if __name__=="__main__": 
    app=QApplication(sys.argv) 
    ex = MainWindow() 
    ex.show() 
    sys.exit(app.exec_()) 

Es funktioniert unter Windows, sondern gibt dem RuntimeError in Linux. Liegt das an einem Unterschied im Multiprocessing-Mechanismus zwischen Windows und Linux? Wie kann ich dasselbe in Linux erreichen?

+0

Was ist der Fehler in vollem Umfang? –

+0

@PeterWood Fehler in Linux: 'RuntimeError: Eine QApplication-Instanz existiert bereits.' Das bedeutet, dass Linux nicht denselben Prozess wie Windows erstellt hat. Ein neuer unter Linux erstellter Prozess kann die QApplication erkennen, die in meinem Main-Prozess ausgeführt wird. – Northern

+0

verwenden Sie ipython unter Linux? – w5e

Antwort

5

Ich habe nach einigen googling von Python Multiprocessing herausgefunden.

Der Punkt ist, hängt von der Plattform multiprocessing unterstützt verschiedene Möglichkeiten, einen neuen Prozess zu starten. Es gibt eine sehr gute Erklärung here. Also, was passiert ist, dass Multiprozessing spawn als Standardmethode in Windows verwenden, während fork als Standardmethode in Linux verwenden. Der Unterschied:

Laich:

The parent process starts a fresh python interpreter process. The child process will only inherit those resources necessary to run the process objects run() method. In particular, unnecessary file descriptors and handles from the parent process will not be inherited.

Gabel:

The parent process uses os.fork() to fork the Python interpreter. The child process, when it begins, is effectively identical to the parent process. All resources of the parent are inherited by the child process.

So kam ich zu einer einfachen Lösung:

Add multiprocessing.set_start_method('spawn') unten if __name__=="__main__":.

set_start_method() ist neu in Version 3.4. Toll, dieses Update zu haben! Ich bin mir nicht sicher, wie ich diesen Parameter in früheren Versionen einstellen soll. Jeder weiß es?

+0

Das ist ausgezeichnet. Netter Fund. –

0

Vielleicht wird Ihnen helfen:

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import multiprocessing 
import sys 


class MainWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     btn = QPushButton('run new instance') 
     self.windows = [] 
     btn.clicked.connect(self.create_window) 
     self.setCentralWidget(btn) 

    def create_window(self): 
     self.windows.append(ChildWindow()) 

class ChildWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(ChildWindow, self).__init__(parent) 
     self.show() 

if __name__=="__main__": 
    app=QApplication(sys.argv) 
    ex = MainWindow() 
    ex.show() 
    sys.exit(app.exec_()) 

habe ich PyQt4, weil ich wollte nicht pyside dafür installieren. Ich denke, es gibt einige Unterschiede in den qt-Librarys auf Cross-Plattformen, so dass die Linux-Anwendung nur eine Instanz der q-Anwendung zulässt.

Here is a mailing list with the same problem => "PySide unterstützt nur das Erstellen einer einzelnen persistenten Instanz von QApplication. Dieser Singleton existiert für immer und kann nicht gelöscht werden."