如何从控制台使用多处理库(使用 map_async)启动 python 脚本

Posted

技术标签:

【中文标题】如何从控制台使用多处理库(使用 map_async)启动 python 脚本【英文标题】:How to start a python script using the multiprocessing library (with map_async) from the console 【发布时间】:2021-05-08 18:38:09 【问题描述】:

对于这个相当长的问题,我很抱歉,但由于这是我在 *** 上的第一个问题,我想彻底地描述我的问题以及我已经尝试过的问题。 我正在模拟随机过程,并认为使用多处理来提高模拟速度是个好主意。由于各个进程不需要相互共享信息,这实际上是多处理的一个微不足道的应用程序——不幸的是,我很难从控制台调用我的脚本。 我的 testfunction 代码如下所示:

#myscript.py
from multiprocessing import Pool

def testFunc (inputs):
    print(inputs)

def multi():
    print('Test2')
    pool = Pool()
    pool.map_async(testFunc, range(10))

if __name__ == '__main__':
    print('Test1')
    multi()

只要我从我的 Spyder IDE 中运行代码,这绝对可以正常工作。作为下一步,我想在我通过 slurm 脚本访问的大学集群上执行我的脚本;因此,我需要能够通过 bash 脚本执行我的 python 脚本。在这里,我得到了一些意想不到的结果。 我在装有 ios 10.15.7 的 Mac Book Pro 和装有 Ubuntu 18.04.5 的工作站上尝试过以下控制台输入:python myscript.pypython -c "from myscript import multi; multi()"。 在每种情况下,我唯一的输出是Test1Test2,而testFunc 似乎从未被调用过。按照这个答案Using python multiprocessing Pool in the terminal and in code modules for Django or Flask,我还尝试了省略if __name__ == '__main__'并将相关功能导入另一个模块的各种版本。例如我试过`

#myscript.py
from multiprocessing import Pool

def testFunc (inputs):
    print(inputs)

pool = Pool()
pool.map_async(testFunc, range(10))

但一切都没有占上风。更让我困惑的是,我现在发现首先打开控制台的 python 解释器只需输入python,按回车然后执行

from myscript import multi
multi()

在 python 解释器中确实工作。 正如我所说,我对此感到非常困惑,因为我认为这相当于python -c "from myscript import multi; multi()",我真的不明白为什么一个有效而另一个无效。为了重现这一成功,我还尝试执行以下 bash 脚本

python - <<'END_SCRIPT'
from multiTest import multi
multi()
END_SCRIPT

但是,唉,这也行不通。 作为最后一次“发现”,我发现所有这些问题仅在使用 map_async 而不仅仅是 map 时出现 - 但是,我认为对于我的应用程序而言,异步进程更可取。

如果有人能解开这个谜团,我将不胜感激(至少对我来说这是一个谜)。 另外,正如我所说,这是我在 *** 上的第一个问题,所以如果我忘记了相关信息或不小心没有遵循格式指南,我深表歉意。非常感谢所有帮助我在未来改进我的问题(和答案)的 cmets 或编辑!

【问题讨论】:

【参考方案1】:

在程序退出之前,您无需等待池完成它正在执行的操作。

def multi():
    print('Test2')
    with Pool() as pool:
        result = pool.map_async(testFunc, range(10))
        result.wait()

如果子流程处理事物的顺序不相关,我建议

with Pool() as pool:
    for result in pool.imap_unordered(testFunc, range(10), 5):
        pass

(更改5,块大小参数,以品尝。)

【讨论】:

哇...感谢您提供非常快速且有用的答案!这确实有效!我仍然对(在我的原始代码中)python -c "from myscript import multi; multi()" 产生与首先使用python 进入 python 解释器然后在解释器中编写 python 代码不同的结果感到困惑。知道为什么这两种方法不同吗? 当您以交互模式进入解释器时,在您输入内容后它会继续运行,并且子进程有时间在它们的主进程退出之前完成它们的工作。如果您使用-c,就像您刚刚拥有一个包含-c 内容的文件一样。您可以使用-i -c ... 运行命令,然后进入交互模式。

以上是关于如何从控制台使用多处理库(使用 map_async)启动 python 脚本的主要内容,如果未能解决你的问题,请参考以下文章

使用多处理时出现 PicklingError

multiprocessing.Pool:map_async 和 imap 有啥区别?

处理对象方法的Python3多处理池未获取对象的更新数据

多处理:将数组列表传递(和迭代)到池映射

Python:如何检查 multiprocessing.Pool 中待处理任务的数量?

multiprocessing.Pool.map_async() 的结果是不是以与输入相同的顺序返回?