多进程问题 [PyQt, py2exe]

16

我正在使用PyQt4编写GUI程序。在我的主窗口中有一个按钮,当单击该按钮时,我希望启动后台进程,该进程是从processing.Process派生的类的实例。

class BackgroundTask(processing.Process):
    def __init__(self, input):
        processing.Process.__init__(self)
        ...

    def run(self):
        ...

(请注意,我正在使用基于Python2.5的python-multiprocessing端口, 这个端口从http://code.google.com/p/python-multiprocessing/获取, 这就是为什么它是processing.Process而不是multiprocessing.Process。 我猜这不应该有区别。我是对的吗?)

与按钮点击信号连接的代码非常简单,如下:

 processing.freezeSupport()
 task = BackgroundTask(input)
 task.start()
程序在Python解释器下运行时(即从命令行“python myapp.py”启动时),如预期工作。
但是,当我使用py2exe打包程序后,每次单击按钮时,不会启动后台任务,而是弹出主窗口的副本。我不确定这种行为的原因。我猜测这与以下注释有关,该注释在http://docs.python.org/library/multiprocessing.html#multiprocessing-programming中提到:
“此软件包中的功能要求子进程可以导入主方法。 尽管编程指南涵盖了此问题,但是在这里指出也很重要。 这意味着一些示例(例如multiprocessing.Pool示例)在交互式解释器中无法正常工作。”
我在主模块中唯一使用“if name == 'main'”是在典型的pyqt程序中。
if __name__ == "__main__":
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
    w = MainWindow()
    w.show()
    a.exec_()

有没有解决这个问题的方法?谢谢!


你能澄清一下吗:你是否已按多进程文档所述保护了主模块?或者你没有访问主模块的权限(我不知道pyqt如何工作)?同时,检查一下你是否正在使用最新版本的py2exe。我曾经遇到过问题,后来发现是由于py2app/py2exe版本过旧导致的。 - James
感谢您的评论。我刚刚在我的帖子中添加了__name__ == "main"部分。不确定是否正在保护主模块。我从http://sourceforge.net/projects/py2exe/files/找到的最新版本的py2exe是在2008-11-16发布的,所以我认为我正在使用最新版本的py2exe。 - Bing Jian
3个回答

26
我认为你实际的问题与此有关:
程序在Python解释器下按预期工作,即如果从命令行启动“python myapp.py”。
然而,当我使用py2exe打包程序之后,每次单击该按钮时,>不会启动后台任务,而是会弹出主窗口的副本。
你需要添加一个特殊的调用freeze_support()函数,以使multiprocessing模块能够与“冻结”的可执行文件(例如,使用py2exe制作的文件)一起工作:
if __name__ == "__main__":
    # add freeze support
    processing.freeze_support()
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
    w = MainWindow()
    w.show()
    a.exec_()

参考文献:http://docs.python.org/library/multiprocessing.html#multiprocessing.freeze_support


1
+1:之前遇到过完全相同的问题,使用了完全相同的解决方法。 - Torsten Marek
1
非常感谢。它起作用了!我知道这个freeze_support()函数,但我没有把它放在正确的位置。我把它放在每次创建新进程实例之前,似乎不起作用。 - Bing Jian

0

这个包内的功能需要子类能够导入主方法。

我认为这意味着你必须在某个地方定义main()函数。


0
问题涉及Python 2,已得到解决。对于Python 3,它将如下所示:
from multiprocessing import freeze_support

if __name__ == '__main__':
    freeze_support()

    a = QApplication(sys.argv)
    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接