来自concurrent.futures库的ProcessPoolExecutor中的奇怪行为



在下面的代码中,每个进程(包括主进程(打印发生一次,因为如示例中所示,我有 2 个进程,语句打印 3 次。我希望它只运行一次,因为每个子进程应该只执行目标函数。

第二个问题,访问变量对我来说似乎不一致,因为我可以访问dic变量并增加其值,但是尝试使用变量number执行此操作时出现错误。

import concurrent.futures as cf
print("Not inside of the target funtion!")
num = 0
dic = {"X":1, "Y":0}
def target(n):
dic["X"] += 1
dic[n] = n
print(dic)
# print(dic["X"])
try:
print(num)
num += 1
except Exception as e:
print(e)
if __name__ == '__main__':
with cf.ProcessPoolExecutor(2) as ex:
ex.map(target, range(3))
print(dic)
# Output 
# Not inside of the target funtion!
# Not inside of the target funtion!
# {'X': 2, 'Y': 0, 0: 0}
# local variable 'num' referenced before assignment
# {'X': 3, 'Y': 0, 0: 0, 1: 1}
# local variable 'num' referenced before assignment
# {'X': 4, 'Y': 0, 0: 0, 1: 1, 2: 2}
# local variable 'num' referenced before assignment
# Not inside of the target funtion!
# {'X': 1, 'Y': 0}

ex.map(target, range(3))创建3个需要执行的任务。诚然,您只有 2 个进程来运行这些进程,因此第三个任务只需等待另一个任务完成即可运行。池中的进程是可重用的。这就是进程池的全部意义所在。进程池大小大于计算机上的处理器数是没有意义的,因为该数字最终决定了可以支持的多处理级别。

但是,对于每个进程执行,如@martineau所述,代码被重新导入,但测试if __name__ == '__main__'失败。这就是为什么你看到"Not inside of the target funtion!"打印了 3 次,但你不会进入一个循环,不断地启动 3 个新流程。

您需要在函数target的开头插入一个global num语句:

变量num是一个全局变量。如果您所做的只是读取变量而不是在函数中修改它,则无需执行任何操作。否则,必须在函数中将其声明为global num。您对dic没有同样的问题,因为您没有修改dicdic是一个引用,您正在修改dic引用的内容,即字典中的键为"X"的值。

相关内容

  • 没有找到相关文章

最新更新