当脚本放入exe时执行pp.Server()时,PyQt会创建另一个主窗口

时间:2012-05-07 15:36:26

标签: python pyqt parallel-processing exe

我正在开发一些旨在作为独立应用程序分发的小python。 我想使用并行python,因为它可以帮助我更快地执行。 通过以下示例,当我通过pyinstaller创建可执行文件时,当它调用pp.Server()时,它会启动一个新窗口。当我关闭新窗口时,会出现管道错误。

以下是出现此问题的脚本示例:

import pp, os, sys, multiprocessing
from bs4 import BeautifulSoup as Soup
from PyQt4 import QtCore, QtGui


try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(188, 119)
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setText(QtGui.QApplication.translate("MainWindow", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.horizontalLayout.addWidget(self.pushButton)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        pass

class TestClass(object):
    __slots__ = ('var')
    def __init__(self): 
        self.var = 'a string'
    def doSomething (self, input_string) : 
        self.var = input_string

class PPTask (object) :
    def __init__ (self) :
        pass
    def ppTask(self, file = '') :
        html = open(file).read()
        soup = Soup(html)
        ret_results = []
        for i in xrange(10) : 
            tc = parallel_tests.TestClass()
            s = str(soup.title.string) # if it is not put in string it won't work in multithreading....
            #~ tc.doSomething(soup.title.string) # this doesn't works
            tc.doSomething(s) # this works if s is a string not a "soup string"
            ret_results.append(tc)
        return ret_results

class Window(QtGui.QMainWindow) : 
    def __init__ (self, parent = None) :
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.createSignals()
    def createSignals(self): 
        QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), self.doItBaby)
    def doItBaby (self) :
        print('it works until here ')
        try : 
            job_server = pp.Server() # this creates a new mainwindow ! 
        except Exception, e : 
            print("I supposed you've just closed the new window created haven't you? " + str(e))
        job_list = []
        results = []
        cmpt = 0
        for i in xrange(100) : 
            pt = PPTask()
            job_list.append(job_server.submit(pt.ppTask, ('anHTMfile.htm',),modules = ("parallel_tests","from bs4 import BeautifulSoup as Soup")))
        for job in job_list : 
            results.append(job())
        for result in results :
            for item in result :
                print 'cmpt = ' + str(cmpt)
                cmpt += 1
                print item.var

if __name__ == '__main__':
    multiprocessing.freeze_support()    
    current_dir = os.getcwd()
    app = QtGui.QApplication(sys.argv)
    ui = Window()
    ui.show()
    sys.exit(app.exec_())

我尝试添加freeze_support(),但它没有像我预期的那样有用。

如果有人能帮助我,我将不胜感激。

2 个答案:

答案 0 :(得分:0)

我还没有尝试过,但可能是因为如果关闭新窗口,就不再有对象的引用了,它会被垃圾收集。
无论如何,在gui中发生所有这些事情都不是很好的设计。

答案 1 :(得分:0)

似乎并行python没有正式的冻结支持。其他人似乎通过py2exe遇到了同样的问题:
http://www.parallelpython.com/component/option,com_smf/Itemid,1/topic,161.0/wap2,wap2

如果您只是使用该模块,则使用多处理冻结会起作用,但它对PP模块没有影响。

问题是它再次启动您的主应用程序而不是工作人员,因此您最终会看到应用程序的另一个实例。 PP使用IPC进行通信,因此当你杀死窗口时,你会杀死它的通信管道并抱怨PP。