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

时间:2021-04-02 07:06:14

I am using Qt for developing GUI applications.

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

I get an error when I try to create another QApplication using multiprocessing:

当我尝试使用多处理创建另一个QApplication时出错:

RuntimeError: A QApplication instance already exists

RuntimeError:QApplication实例已存在

I have a main window, which contains a button for spawning a new process so that I can create a new GUI instance. Basically like this:

我有一个主窗口,其中包含一个用于生成新进程的按钮,以便我可以创建一个新的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_())

It works in Windows but gives the RuntimeError in Linux. Is this because of difference in multiprocessing mechanism between Windows and Linux? How could I achieve the same thing in Linux?

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

2 个解决方案

#1


7  

I figured out after some googling of python multiprocessing.

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

The point is, depends on the platform multiprocessing supports different ways to start a new process. There is a very good explanation here. So, what happens is that multiprocessing use spawn as the default method in Windows, while use fork as the default method in Linux. The Difference:

关键是,取决于平台多处理支持不同的方式来启动新进程。这里有一个非常好的解释。因此,会发生的事情是多处理使用spawn作为Windows中的默认方法,而使用fork作为Linux中的默认方法。区别:

spawn:

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.

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

fork:

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.

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

Thus, I came to a simple solution:

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

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

如果__name __ ==“__ main__”,请添加multiprocessing.set_start_method('spawn')。

set_start_method() is new in version 3.4. Great to have this update! I am not sure how to set this parameter in previous versions. Anyone knows?

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

#2


0  

Maybe this is helping you:

也许这有助于你:

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

I used pyqt4 because i don't wanted to install pyside for that. I think that there are some diffrences in the qt-librarys on cross-plattforms, so that the linux application only allows one instance of the qapplication.

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

Here is a mailing list with the same problem => "PySide only supports creating a single persistent instance of QApplication. This singleton exists forever and cannot be deleted."

这是一个具有相同问题的邮件列表=>“PySide仅支持创建QApplication的单个持久化实例。这个单例永远存在且无法删除。”

#1


7  

I figured out after some googling of python multiprocessing.

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

The point is, depends on the platform multiprocessing supports different ways to start a new process. There is a very good explanation here. So, what happens is that multiprocessing use spawn as the default method in Windows, while use fork as the default method in Linux. The Difference:

关键是,取决于平台多处理支持不同的方式来启动新进程。这里有一个非常好的解释。因此,会发生的事情是多处理使用spawn作为Windows中的默认方法,而使用fork作为Linux中的默认方法。区别:

spawn:

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.

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

fork:

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.

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

Thus, I came to a simple solution:

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

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

如果__name __ ==“__ main__”,请添加multiprocessing.set_start_method('spawn')。

set_start_method() is new in version 3.4. Great to have this update! I am not sure how to set this parameter in previous versions. Anyone knows?

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

#2


0  

Maybe this is helping you:

也许这有助于你:

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

I used pyqt4 because i don't wanted to install pyside for that. I think that there are some diffrences in the qt-librarys on cross-plattforms, so that the linux application only allows one instance of the qapplication.

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

Here is a mailing list with the same problem => "PySide only supports creating a single persistent instance of QApplication. This singleton exists forever and cannot be deleted."

这是一个具有相同问题的邮件列表=>“PySide仅支持创建QApplication的单个持久化实例。这个单例永远存在且无法删除。”