繁体   English   中英

通过多处理将动态加载的函数用作目标

[英]Using a dynamically loaded function as a target with multiprocessing.Pool

我正在使用一个GUI,该GUI需要在后台进行一些繁重的计算,然后在计算完成后更新GUI。 多重处理模块似乎是一个很好的解决方案,因为我可以使用* apply_async *方法指定目标和回调函数。 回调函数用于使用结果更新GUI。 但是,当尝试将多处理与动态加载的模块结合在一起时,如下面的代码所示,我遇到了困难。 错误消息是ImportError:没有名为calc的模块。

错误是由于多处理功能不适用于动态加载的模块吗? 如果没有,是否有更好的想法?

from PySide.QtCore import *
from PySide.QtGui import *
import multiprocessing
import time
import sys
import os
import logging
import imp

PluginFolder = "plugins"
plugins = {}

def f(x):
    y = x*x
    time.sleep(2) #Simulate processing time.
    return y


def load_plugin(name):
    '''Load the python module 'name'
    '''
    location = os.path.join('.', PluginFolder)
    info = imp.find_module(name, [location])
    plugin = {"name": name, "info": info}
    plugins[name] = imp.load_module(name, *plugin["info"])


class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.pool = multiprocessing.Pool() 
        load_plugin('calc') #load ./plugins/calc.py

        button1 = QPushButton('Calculate', self)
        button1.clicked.connect(self.calculate)
        button2 = QPushButton('Test', self)
        button2.clicked.connect(self.run_test)
        self.text = QTextEdit()

        vbox1 = QVBoxLayout()
        vbox1.addWidget(button1)
        vbox1.addWidget(button2)
        vbox1.addWidget(self.text)
        myframe = QFrame()
        myframe.setLayout(vbox1)

        self.setCentralWidget(myframe)
        self.show()
        self.raise_()



    def calculate(self):
        #self.pool.apply_async(f, [10], callback=self.update_gui) #This works

        #result = plugins['calc'].f(10) #this works
        #self.update_gui(result)

        self.pool.apply_async(plugins['calc'].f, [10], callback=self.update_gui) #This doesn't


    def update_gui(self, result):
        self.text.append('Calculation complete. Result = %d\n' % result)


    def run_test(self):
        self.text.append('Testing\n')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = MainWindow()
    app.exec_()

在./plugins/calc.py中,函数f如上述代码中所定义。

这不起作用,因为您将calc模块作为顶级模块加载。 由于sys.path或当前目录中不存在模块calc ,因此import语句无法找到它。 用下面的代码替换import语句可以达到目的:

plugins[name] = imp.load_module('{}.{}'.format(PluginFolder, name), 
                     *plugin["info"])

对于可导入的plugin.calcplugins必须是python模块,即包含__init__.py文件。

插件文件中的所有import <module>语句(例如plugins/calc.py )都会导致警告,

RuntimeWarning: Parent module 'plugins' not found while handling absolute import import <module>

原因是导入过程会查找父模块是否包含<module> ,而在calc.py ,则找不到父plugins模块。 您可以使用例如主代码中的import plugins语句来消除明确指定plugins模块位置的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM