使用Qt进行多处理适用于Windows,但不适用于Linux

时间:2015-04-10 08:03:12

标签: python linux pyqt python-multiprocessing

我正在使用Qt开发GUI应用程序。

当我尝试使用QApplication创建另一个multiprocessing时出现错误:

  

RuntimeError:QApplication实例已存在

我有一个主窗口,其中包含一个用于生成新进程的按钮,以便我可以创建一个新的GUI实例。基本上是这样的:

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

它适用于Windows但在Linux中提供RuntimeError。 这是因为Windows和Linux之间的多处理机制存在差异吗?我怎么能在Linux中实现同样的目标呢?

2 个答案:

答案 0 :(得分:7)

我在一些谷歌搜索python多处理后想通了。

重点是,取决于平台multiprocessing支持不同的方式来启动新进程。有一个很好的解释here。 因此,多处理使用spawn作为Windows中的默认方法,而使用fork作为Linux中的默认方法。差异:

菌种:

  

父进程启动一个新的python解释器进程。子进程只会继承运行进程对象run()方法所需的那些资源。特别是,不会继承父进程中不必要的文件描述符和句柄。

叉:

  

父进程使用os.fork()来分叉Python解释器。子进程在开始时实际上与父进程相同。父进程的所有资源都由子进程继承。

因此,我找到了一个简单的解决方案:

multiprocessing.set_start_method('spawn')下面添加if __name__=="__main__":

set_start_method()是3.4版中的新功能。很高兴有这个更新!我不知道如何在以前的版本中设置此参数。有人知道吗?

答案 1 :(得分:0)

也许这有助于你:

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

我使用了pyqt4,因为我不想为此安装pyside。我认为qt-librarys在跨平台上存在一些差异,因此linux应用程序只允许qapplication的一个实例。

Here is a mailing list with the same problem => " PySide仅支持创建QApplication的单个持久化实例。这个单例永远存在,无法删除。"