Python Pool.Starmap 未在打印时终止或输出

Posted

技术标签:

【中文标题】Python Pool.Starmap 未在打印时终止或输出【英文标题】:Python Pool.Starmap Not Terminating Or Outputting on Print 【发布时间】:2021-12-23 12:20:38 【问题描述】:

我尝试了几种不同的方式来执行Pool.starmap。我尝试了各种不同的建议和答案,但无济于事。下面是我尝试运行的代码示例,但是它被捕获并且永远不会终止。我在这里做错了什么?

旁注:我使用的是python版本3.9.8

if __name__ == '__main__':
with get_context("spawn").Pool() as p:
    tasks = [(1,1),(2,2),(3,3)]
    print(p.starmap(add,tasks))
    p.close()
    p.join()

【问题讨论】:

当为Pool 使用with 上下文时,您不需要closejoin 池。这就是 with 上下文为您所做的。 【参考方案1】:

python 中的多处理具有一些您应该注意的复杂性,这使得它取决于您运行脚本的方式以及您使用的操作系统和 python 版本。

我经常看到的一个大问题是 Jupyter 和其他“笔记本”风格的 Python 环境并不总是能很好地支持多处理。从技术上讲,有一些方法可以解决这个问题,但我通常只是建议从更正常的系统终端执行代码。共同点是“交互式”解释器不能很好地工作,因为需要有一个“主”文件,而在交互模式下没有文件;它只是等待用户输入。

我无法确切知道您的问题是什么,因为您没有提供所有代码、您正在使用的操作系统以及您正在使用的 IDE,但我至少可以为您提供一个工作 (在我的设置上)示例。 (windows 10;python 3.9;带有运行设置的 Spyder IDE -> 在外部系统终端中执行)

import multiprocessing as mp

def add(a, b): #I'm assuming your "add" function looks a bit like this...
    return a+b

if __name__ == "__main__": 
    #this is critical when using "spawn" so code doesn't run when the file is imported
    #you should only define functions, classes, and static data outside this (constants)
    #most critically, it shouldn't be possible for a new child process to start outside this
    
    ctx = mp.get_context("spawn")
    #This is the only context available on windows, and the default for MacOS since python 3.8.
    #  Contexts are an important topic somewhat unique to python multiprocessing, and you should
    #  absolutely do some additional reading about "spawn" vs "fork". tldr; "spawn" starts a new
    #  process with no knowledge of the old one, and must `import` everything from __main__. 
    #  "fork" on the other hand copies the existing process and all its memory before branching. This is
    #  faster than re-starting the interpreter, and re-importing everything, but sometimes things
    #  get copied that shouldn't, and other things that should get copied don't.
    with ctx.Pool() as p: 
        #using `with` automatically shuts down the pool (forcibly) at the end of the block so you don't have to call `close` or `join`.
        #  It was also pointed out that due to the forcible shutdown, async calls like `map_async` may not finish unless you wait for the results
        #  before the end of the `with` block. `starmap` already waits for the results in this case however, so extra waiting is not needed.
        tasks = [(1,1),(2,2),(3,3)]
        print(p.starmap(add, tasks))

【讨论】:

一个小点:退出with块只会调用p.terminate(),所以如果有任何任务正在运行或计划运行,它们将被杀死。 @Booboo TIL...谢谢!但是,starmap 在这种情况下是同步的,因此无论如何都应该完成所有处理。但是,对于 Pool 的任何异步函数,了解这一点很重要。它遵循这样的做法:在 join 处理进程(或本例中的池)之前,您应该始终从队列中得到 get 结果。

以上是关于Python Pool.Starmap 未在打印时终止或输出的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Pool.starmap_async() 中获取结果?

Python 多线程池 Windows 冻结

Python多处理池:完成任何k个作业后终止进程

日志未在设备中打印

尽管正确打印出所有输出,但程序未在 Java 中以退出代码 0 结束

在创建 pdf 时,图像未在 Flutter 中显示