繁体   English   中英

multiprocessing.pool 行为改变——不起作用,抱怨 freeze_support

[英]multiprocessing.pool behavior change — doesn't work, complains about freeze_support

这是一个并行执行工作的简单脚本:

import multiprocessing as mp

def f(x):
    return x+1

pool = mp.Pool(2)
res = pool.map(f, range(10))
pool.close()
print(res)

它曾经只是工作。 最近,它没有。 我不知道发生了什么变化,也许是 python 更新?

编辑:它在 python 3.7.4 中工作正常,但在 3.8.3 中没有

当我从 ipython 运行它(特别是使用 spyder)时,我得到以下内容,而且是无限的:

Process SpawnPoolWorker-1:
Traceback (most recent call last):
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/pool.py", line 114, in worker
    task = get()
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/queues.py", line 358, in get
    return _ForkingPickler.loads(res)
AttributeError: Can't get attribute 'f' on <module '__main__' (built-in)>
Process SpawnPoolWorker-2:
Traceback (most recent call last):
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/pool.py", line 114, in worker
    task = get()
  File "/opt/anaconda3/envs/two_step_line/lib/python3.8/multiprocessing/queues.py", line 358, in get
    return _ForkingPickler.loads(res)
AttributeError: Can't get attribute 'f' on <module '__main__' (built-in)>
Process SpawnPoolWorker-3:

这曾经只是工作。 我在 Mac 上使用 python 3.8.3,脚本在 python 3.7.4 上运行。

更重要的是,我该如何解决这个问题?

EDIT2:我发现我可以把它包起来

if __name__ == "__main__":
    pool...

如果我将脚本保存到 .py 文件,它将从命令行中查找。 但它不能交互工作。 我通常以交互方式进行开发,这种变化很烦人。 有谁知道如何在 python 3.8.3 中交互式运行简单的mp循环?

Edit3:显然,问题源于这样一个事实,即 3.8 中的多处理现在确实在 mac 上默认spawn而不是fork ,根据this 出于某种原因,分叉是“不安全的”。 我不关注讨论,但一个简单的、可能“不安全”的解决方法是

mp.set_start_method('fork')

过去几天我一直在使用 Spyder 中的 Pool 进行多处理,我遇到了与您类似的问题。 我无法以交互方式运行任何多处理代码(作为代码块),但我能够让多处理代码运行:

from multiprocessing import Pool

def main():
    with Pool(5) as p:
         ...do multiprocessing here

if __name__ == "__main__":
    main()

当我按绿色播放按钮(或 F5)运行文件时,多处理代码正确执行。

经过大量的挖掘和几个死胡同,我把一些可行的东西放在一起。 只需对我们的代码进行少量重组,我们就可以在 Spyder4 中实现交互式多处理。

首先,我们需要确保我们使用的是 IPython 控制台。 我们可以通过在 Spyder 中重新启动控制台并验证是否打印了“IPython 7.xx.x”来确认这一点。

其次,我们需要将我们想要交互的多处理代码移动到另一个文件中,并将其包装在 main() 中。 这是一个可能看起来像的示例(暂时忽略有关varFromInteractive的警告 - 这将来自交互式代码单元的部分):

from multiprocessing import Pool

def f(a):
    return a**2

def multiprocessTest():
    with Pool(5) as p:
        out = p.map(f, range(varFromInteractive))
    return out

def main():
    print('executing test.py')
    testing = multiprocessTest()
    print('multiprocessing results: ', testing)
    
varFromTest = 'it worked!'

if __name__ == "__main__":
    main()

假设我们将上述多处理代码保存在文件 test.py 中。

接下来,在我们希望运行的单个单元格的交互式文件中(通过键入# %%创建单元格),我们可以输入:

# %%    
from IPython import get_ipython

# %%
varFromInteractive = 10
get_ipython().run_line_magic('run', '-i test.py')

# %%
print(varFromTest)

运行这三个单元时,我收到了 output:

runcell(19, 'C:/Users/redacted/exploration.py')

runcell(27, 'C:/Users/redacted/exploration.py')
executing test.py
multiprocessing results:  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

runcell(28, 'C:/Users/redacted/exploration.py')
it worked!

这太棒了,因为不仅多处理代码正在执行,而且 test.py 中的多处理代码可以访问变量varFromInteractive ,并且单独文件中的交互式代码可以访问变量varFromTest

那么让这项工作有什么魔力呢? 好吧,顺便说一下,IPython 的魔法。

get_ipython().run_line_magic('run','-i test.py')行告诉 IPython shell 执行包含在文件test.py中的代码,其中-i参数表示“在 IPython 的命名空间中运行文件”一个空的” [来源] 此外,“该文件在最初仅由 __name__=='__main__' 和所示构造的 sys.argv 组成的命名空间中执行” [same source]

据我了解,Spyder 曾经在代码单元中原生支持 IPython 魔法,因此可以编写%run -i test.py 情况不再如此,如此 github 问题中所述:

IPython 魔法不是有效的 Python 代码,因此我们决定不再在 Python 文件中支持它们。 这将避免文件在 Spyder 中工作但不在 Spyder 之外的常见问题。

该信息的发布者 ccordoba12 还给出了如何在 Spyder4 中使用 IPython 魔法的示例:

from IPython import get_ipython
get_ipython().magic('who print')

该信息与上面链接的 IPython 文档和这些 IPython 文档相结合以产生解决方案。

问题的海报使用Mac,我使用Windows PC,但我希望解决方案能够翻译。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM