Python多进程嵌套函数变量修改失效问题求助
问题描述
我写了一个Python多进程示例,遇到变量修改不生效的问题:在单层函数中用Manager可以正常实现全局计数,但使用两层嵌套函数时,内层函数对变量的修改无法传递到外层函数,结果不符合预期。
代码如下:
from multiprocessing import Process, Manager import os def ff(b): b = b +1 print('def ff b = ', b) print('parent process:', os.getppid()) print('process id:', os.getpid()) print() def f(a): b = 0 ff(b) a.value = a.value + b print('def f a = ', a.value, ' b = ', b) print('parent process:', os.getppid()) print('process id:', os.getpid()) print() if __name__ == '__main__': manager = Manager() a = manager.Value('i', 0) p = Process(target=f, args=(a,)) p.start() p.join() print('Main, a = ', a.value) print('parent process:', os.getppid()) print('process id:', os.getpid())
实际输出:
def ff b = 1 parent process: 12312 process id: 2320 def f a = 0 b = 0 parent process: 12312 process id: 2320 Main, a = 0 parent process: 21296 process id: 12312
预期输出:
def f return b = 1 and a = 1 Main return a = 1
提问:请问我哪里出错了?如何让进程内的变量实现全局修改?
问题分析与解决
错误原因
你的问题和多进程无关,核心是Python不可变对象的参数传递机制。b是整数(不可变类型),调用ff(b)时传递的是b的副本,内层ff里的b = b+1只是修改了函数内部的局部变量,和外层f中的b没有任何关联,所以外层b的值始终是0,最终a.value也不会变化。
解决方法
方法1:让内层函数返回修改后的值
修改内层函数ff,让它返回更新后的b值,外层f接收该值并重新赋值给b,这是最直观的方式:
from multiprocessing import Process, Manager import os def ff(b): b = b +1 print('def ff b = ', b) print('parent process:', os.getppid()) print('process id:', os.getpid()) print() return b # 返回修改后的值 def f(a): b = 0 b = ff(b) # 接收返回值,更新外层b a.value = a.value + b print(f'def f return b = {b} and a = {a.value}') print('parent process:', os.getppid()) print('process id:', os.getpid()) print() if __name__ == '__main__': manager = Manager() a = manager.Value('i', 0) p = Process(target=f, args=(a,)) p.start() p.join() print(f'Main return a = {a.value}') print('parent process:', os.getppid()) print('process id:', os.getpid())
运行后会得到符合预期的输出:
def ff b = 1 parent process: 12312 process id: 2320 def f return b = 1 and a = 1 parent process: 12312 process id: 2320 Main return a = 1 parent process: 21296 process id: 12312
方法2:用可变容器传递变量
如果需要在嵌套函数中直接修改外层变量,可将b放入可变容器(比如列表)中,因为可变对象传递的是引用,修改容器内的元素会直接影响外层:
from multiprocessing import Process, Manager import os def ff(b_list): b_list[0] += 1 # 修改列表内的元素 print('def ff b = ', b_list[0]) print('parent process:', os.getppid()) print('process id:', os.getpid()) print() def f(a): b_list = [0] # 用列表存储b ff(b_list) b = b_list[0] a.value = a.value + b print(f'def f return b = {b} and a = {a.value}') print('parent process:', os.getppid()) print('process id:', os.getpid()) print() if __name__ == '__main__': manager = Manager() a = manager.Value('i', 0) p = Process(target=f, args=(a,)) p.start() p.join() print(f'Main return a = {a.value}') print('parent process:', os.getppid()) print('process id:', os.getpid())
内容的提问来源于stack exchange,提问作者DmitriyN
相关产品推荐
相关产品推荐

