Python: 使用ProcessPoolExecutor执行exec函数

4
from concurrent.futures import ProcessPoolExecutor
import os
import time

def parInnerLoop(item):
    a = 2+item
    print(f'A. {a} Processing {os.getpid()} done on {item}\n')
    exec(open('mainWork.py').read())
    print(f'D. {a} Processing {os.getpid()} done on {item}\n')

def main():
    with ProcessPoolExecutor(max_workers=4) as executor:
        for itemNo in range(10):
            executor.submit(parInnerLoop, itemNo)
    print('done')

if __name__ == '__main__':
    main()

mainWork.py

print(f'B. {a} Processing {os.getpid()} done on {item}\n')
a = 12
print(f'C. {a} Processing {os.getpid()} done on {item}\n')

错误:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "D:\Program Files\Python\Python37\Lib\concurrent\futures\process.py", line 101, in _python_exit
    thread_wakeup.wakeup()
  File "D:\Program Files\Python\Python37\Lib\concurrent\futures\process.py", line 89, in wakeup
    self._writer.send_bytes(b"")
  File "D:\Program Files\Python\Python37\Lib\multiprocessing\connection.py", line 183, in send_bytes
    self._check_closed()
  File "D:\Program Files\Python\Python37\Lib\multiprocessing\connection.py", line 136, in _check_closed
    raise OSError("handle is closed")
OSError: handle is closed

问题:

  1. 错误,在程序结束时出现。
  2. 我想将 mainWork.py 的所有代码作为 parInnerLoop 的一部分执行,以便在 a 的值发生更改时,parInnerLoopmainWork.py 中的值都会反映出来,反之亦然。 我得到的输出如下。当打印从 D. ... 开始时,a 的值不会更改,我希望它是12。

0 项的输出结果:

A. 2 Processing 19784 done on 0
B. 2 Processing 19784 done on 0
C. 12 Processing 19784 done on 0
D. 2 Processing 19784 done on 0

发生了什么?请帮忙。

我最终想要实现的目标:使用不同的设置并行运行相同的代码,而不会互相干扰。

额外信息:

  1. 我已经测试了ProcessPoolExecutor的正常工作,如这里所示。
  2. 我已经使用以下代码测试了exec(open('run.py').read()) 的预期效果:

main.py

def myFun():
    a = 1
    b = 2
    print(a)
    exec(open('run.py').read())
    #execfile("run.py")
    print(a)
    print(b)
    print(c)

def main():
    myFun()

if __name__ == '__main__':
    main()

run.py

a = a+5
b = 10
c = 15

输出

1
6
10
15

1
我在Linux上使用3.7.6时遇到了同样的问题。看起来这是一个未解决的bug。 - nodakai
1
@nokada,我在Windows上使用Python 3.7.8时遇到了同样的问题。看起来这个错误还没有被修复。 - Bernardo Trindade
升级到Python 3.9+以解决此问题。 - Savrige
1个回答

2

这不是完整的答案,但似乎与

感谢您的报告!经过快速调查,似乎问题是由于concurrent.futures模块的最近更改引起的。简而言之,它们维护了一个弱引用字典,指向一些服务线程(名为“QueueManagerThread”),并尝试在退出Python进程时关闭该字典中存在的任何线程。该字典通常为空,但如果对线程的引用存在,则可能会尝试关闭未运行的线程。在这种情况下,将引发原始异常。

https://youtrack.jetbrains.com/issue/PY-34432


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接