使用包装器函数的Multiprocessing异常:全局列表执行后为空
问题原因
Python的multiprocessing.Pool创建的子进程会复制主进程的内存空间,每个子进程都拥有独立的foo列表副本。装饰器里修改的是子进程自己的foo,和主进程的foo完全是两个不同的对象——你可以对比打印的id(foo),子进程里的id和主进程最终打印的id肯定不一样。子进程结束后,它们的内存空间被销毁,所以主进程里的foo根本没被修改过。
解决方法
要实现跨进程共享列表,得用Python多进程提供的共享内存机制,比如multiprocessing.Manager:
import multiprocessing as mp import functools def decorator(f): @functools.wraps(f) def wrapper(*args, **kwargs): foo = args[0] # 把共享列表作为参数传入 foo.append(1) print(id(foo), foo) f(*args[1:], **kwargs) return wrapper @decorator def square(n): return n * n if __name__ == "__main__": with mp.Manager() as manager: foo = manager.list() # 创建共享列表 pool = mp.Pool() # 把共享列表作为第一个参数传给每个任务 pool.map(functools.partial(square, foo), [i for i in range(1, 5)]) print(id(foo), list(foo)) # 这里能看到修改后的结果
如果只是需要收集子进程的输出,也可以用multiprocessing.Queue传递数据,但Manager.list()更适合直接共享列表场景。另外必须加if __name__ == "__main__":,这是Windows系统下多进程的强制要求,避免无限创建子进程。
内容的提问来源于stack exchange,提问作者Peatherfed
相关产品推荐
相关产品推荐

