Python:多处理异常行为

标签 python multithreading multiprocessing

有一个类属性self.class_variable。点击“Press to append One, Two and Three to class_variable list”按钮调用一个外部的 MainWindow()externalFunc() 函数用于追加 'One','Two ','三'。一行:

externalFunc(str(self.i))

用于直接调用 externalFunc() 以将数字附加到相同的 self.class_variable 列表。

按下“Press to print class_variable list”打印出 self.class_variable 的内容。我没有解释为什么

pool.map_async( externalFunc, self.myList )

self.class_variable 没有影响。 self.class_variable 的值保持不变。 请指教。

from PyQt4 import QtCore, QtGui
from multiprocessing import Pool

def externalFunc(arg):
    window.setAttrbitute(arg)


class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.main_layout = QtGui.QVBoxLayout()
        self.class_variable=['InitialValue']

        self.myList=['One','Two','Three']
        self.i=0

        print_button = QtGui.QPushButton('Press to print class_variable list')      
        print_button.clicked.connect(self.printVariable)
        self.main_layout.addWidget(print_button)

        ok_button = QtGui.QPushButton("Press to append One, Two and Three to class_variable list")
        ok_button.clicked.connect(self.append_from_external_using_multi)
        self.main_layout.addWidget(ok_button)       

        central_widget = QtGui.QWidget()
        central_widget.setLayout(self.main_layout)
        self.setCentralWidget(central_widget)

    def setAttrbitute(self, arg):
        print "Appending arg to class_variable: ", arg
        self.class_variable.append(arg)

    def append_from_external_using_multi(self):
        # calling external function dirctly:
        externalFunc(str(self.i))
        # calling external function via pool.map_async:
        pool = Pool(processes=3)
        pool.map_async( externalFunc, self.myList )
        self.i+=1

    def printVariable(self, arg):
        print "\n\t self.class_variable = ", self.class_variable


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.resize(480, 320)
    window.show()
    sys.exit(app.exec_())

根据 J.F. Sebastian 发布的建议修改了工作代码

from PyQt4 import QtCore, QtGui
import multiprocessing as mp

def externalFunc(arg):
    window.setAttrbitute(arg)


class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.main_layout = QtGui.QVBoxLayout()

        self.class_variable=manager.list(['InitialValue'])

        self.myList=['One','Two','Three']

        self.i=0

        print_button = QtGui.QPushButton('Press to print class_variable list')      
        print_button.clicked.connect(self.printVariable)
        self.main_layout.addWidget(print_button)

        ok_button = QtGui.QPushButton("Press to append One, Two and Three to class_variable list")
        ok_button.clicked.connect(self.append_from_external_using_multi)
        self.main_layout.addWidget(ok_button)    

        central_widget = QtGui.QWidget()
        central_widget.setLayout(self.main_layout)
        self.setCentralWidget(central_widget)

    def setAttrbitute(self, arg):
        print "Appending arg to class_variable: ", arg
        self.class_variable.append(arg)

    def append_from_external_using_multi(self):
        # calling external function dirctly:
        externalFunc(str(self.i))
        # calling external function via pool.map_async:
        pool = mp.Pool(processes=3)

        pool.map_async( externalFunc, self.myList )
        self.i+=1

    def printVariable(self, arg):
        print "\n\t self.class_variable = ", self.class_variable


if __name__ == '__main__':
    manager = mp.Manager()

    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.resize(480, 320)
    window.show()
    sys.exit(app.exec_())

最佳答案

它没有效果,因为默认情况下不同的进程不共享对象。通常,您不能在进程之间共享任意 Python 对象。

这是一个说明问题的小例子:

#!/usr/bin/env python
#XXX broken
import multiprocessing as mp

def f(a):
    L.append(a)

if __name__=="__main__":
   L = ['a']
   pool = mp.Pool(1)
   pool.map(f, 'b')
   print(L) # -> ['a'] it hasn't changed in the parent
   assert 'b' not in L

要修复它,您可以通过 multiprocessing.Manager 使用代理对象:

#!/usr/bin/env python
import multiprocessing as mp

def f(a):
    L.append(a)

if __name__=="__main__":
   manager = mp.Manager()
   L = manager.list(['a'])
   pool = mp.Pool(1)
   pool.map(f, 'b')
   print(L)  # -> ['a', 'b'] it has changed in the parent
   assert 'b' in L

注意:由于非 fork() 语义,您可能需要将 L 显式传递给 Windows 上的工作进程,例如:

def init(ll):
    global L
    L = ll

...
pool = mp.Pool(1, initializer=init, initargs=[L])

关于Python:多处理异常行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22240962/

相关文章:

python - 从Python中的配置文件读取 token

python - Sympy ODE 求解器初始条件无效

python - 使用 3 个现有列的条件在 Pandas 数据框中添加一列

xcode - 如何在不阻塞主线程的情况下在 Xcode、单元测试中执行延迟?

java - Thread.sleep() 的 InterruptedException

python - 在 Django View 中显示一对多关系

android - 如何使用 AsyncTask 从 Url 设置图像?

c# - 如何在c#上划分数组?

python - 如何运行多个函数以并行返回各自的列表

python - 多处理:在某些情况下在赋值之前引用变量,但在其他情况下则不会