2015-04-10 14 views
7

Sto usando Qt per lo sviluppo di applicazioni GUI.La multiprocessing con Qt funziona su Windows ma non su Linux

ottengo un errore quando provo a creare un altro QApplication utilizzando multiprocessing:

RuntimeError: A QApplication instance already exists

Ho una finestra principale, che contiene un pulsante per la deposizione delle uova un nuovo processo in modo che io possa creare una nuova istanza GUI. In pratica in questo modo:

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_()) 

Funziona in Windows, ma dà l'RuntimeError in Linux. Ciò è dovuto alla differenza nel meccanismo di multiprocessing tra Windows e Linux? Come potrei ottenere la stessa cosa in Linux?

+0

Qual è l'errore in pieno? –

+0

@PeterWood Errore in Linux: 'RuntimeError: esiste già un'istanza QApplication. Ciò significa che Linux non ha creato lo stesso processo di Windows. Il nuovo processo creato in Linux può rilevare QApplication in esecuzione nel mio processo principale. – Northern

+0

stai usando ipython su linux? – w5e

risposta

5

Ho capito dopo qualche ricerca su google con multiprocessing di python.

Il punto è, dipende dalla piattaforma multiprocessing supporta diversi modi per avviare un nuovo processo. C'è un'ottima spiegazione here. Quindi, quello che succede è che il multiprocessing usa spawn come metodo predefinito in Windows, mentre usa il metodo fork come metodo predefinito in Linux. La differenza:

uova:

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.

forcella:

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.

Così, sono arrivato a una soluzione semplice:

add multiprocessing.set_start_method('spawn') soffietto if __name__=="__main__":.

set_start_method() è una nuova versione 3.4. Ottimo per avere questo aggiornamento! Non sono sicuro di come impostare questo parametro nelle versioni precedenti. Qualcuno lo sa?

+0

Questo è eccellente. Bella scoperta. –

0

Forse questo ti sta aiutando:

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_()) 

ho usato PyQt4 perché io non volevo installare PySide per questo. Penso che ci siano delle diffrenze nelle librerie qt sulle piattaforme incrociate, così che l'applicazione linux consente solo un'istanza di qapplication.

Here is a mailing list with the same problem => "PySide supporta solo la creazione di una singola istanza persistente di QApplicazione Questo singleton esiste per sempre e non può essere eliminato."

Problemi correlati