并发库中ProcessPoolExecutor中的异常行为

问题描述 投票:-1回答:1

在下面的代码中,每个流程(包括主流程)都进行一次打印,因为如示例中所示,我有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}
python python-3.x multiprocessing concurrent.futures
1个回答
2
投票

ex.map(target, range(3))创建需要执行的3个任务。没错,您只有2个进程可以运行这些进程,因此第三个任务将仅等待另一个任务完成才能运行。池中的进程是可重用的。这是流程池的重点。没有任何意义使进程池的大小大于计算机上的处理器数量,因为该数量最终决定了可以支持的多处理级别。

但是,对于每个流程执行,正如@martineau所说,代码会重新导入,但是测试if __name__ == '__main__'失败。这就是为什么您看到"Not inside of the target funtion!"打印了3次,但是却没有陷入不断启动3个新流程的循环的原因。

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

Variable num是全局变量。如果您要做的只是读取变量而不是在函数中修改变量,则无需执行任何操作。否则,必须在函数中将其声明为global num。由于您没有修改dic,因此dic没有相同的问题。 dic是参考,您正在修改dic所指的内容,即字典中键为"X"的值。

© www.soinside.com 2019 - 2024. All rights reserved.