0

我正在研究一些旨在作为独立应用程序分发的小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() 但它并没有像我预期的那样有帮助。

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

4

2 回答 2

0

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

于 2012-05-07T21:30:29.840 回答
0

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

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

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

于 2012-05-08T01:29:54.437 回答