当前位置: 首页 > 知识库问答 >
问题:

Pool.map在4次迭代后挂起

卫嘉泽
2023-03-14

我不熟悉Python和多处理。我想批量转换一堆文件,所以我想尝试多处理。Pool和map()的概念似乎足够简单,但似乎不起作用。我已经在下面将它简化为一个测试程序,但其要点是:它将经过4次迭代(池中的每个进程),然后挂起。以下是测试代码:

import multiprocessing, logging
import os
import sys

mpl = multiprocessing.log_to_stderr()
mpl.setLevel(logging.INFO)

def chill(t):
    cmd  = '/bin/sleep'
    args = (cmd,str(t))
    print >>sys.stderr, os.getpid(), args
    os.execv(cmd, args)

if __name__ == "__main__" :
    times = [ 1 ] * 100
    pool = multiprocessing.Pool(1)  # change this for more processes
    pool.map(chill, times)
    pool.close()
    pool.join()

当我运行它时,它在第四次迭代后挂起。增加进程数只会使其挂起为进程数的4倍。这个“4”有什么神奇之处?我做错了什么?

共有1个答案

商俊智
2023-03-14

问题是os.execv替换了子进程,因此父进程和子进程之间的常规握手丢失了。如果进程意外退出,mp将重新启动进程并发送另一个块。您可能已经在多重处理模块中发现了一个错误,因为它在这种异常情况下继续发送数据到进程,然后挂起等待永远不会到达的任务完成。

解决方案是使用诸如子流程之类的函数。调用对要运行的代码执行完整的fork和exec。这样子进程就可以灵活地将结果传递回父进程。

通过对测试程序进行一些更改,可以更清楚地看到这个问题。

import multiprocessing, logging
import os
import sys
import subprocess as subp

mpl = multiprocessing.log_to_stderr()
mpl.setLevel(logging.INFO)

def chill(args):
    i, t = args
    cmd  = '/bin/sleep'
    args = (cmd,str(t))
    print >>sys.stderr, i, os.getpid(), args
    os.execv(cmd, args)
#    subp.call(['/bin/sleep', str(t)])

if __name__ == "__main__" :
    times = [(i,1) for i in range(100)]
    pool = multiprocessing.Pool(1)  # change this for more processes
    pool.map(chill, times)
    pool.close()
    pool.join()

map已将工作分成4个块,然后在最后一个块后挂起

[INFO/PoolWorker-1] child process calling self.run()
0 9204 ('/bin/sleep', '1')
[INFO/PoolWorker-2] child process calling self.run()
25 9208 ('/bin/sleep', '1')
[INFO/PoolWorker-3] child process calling self.run()
50 9209 ('/bin/sleep', '1')
[INFO/PoolWorker-4] child process calling self.run()
75 9210 ('/bin/sleep', '1')
[INFO/PoolWorker-5] child process calling self.run()
 类似资料:
  • 我正在尝试获取一个

  • 我试图在PHP中的foreach循环的每次迭代之后进行回显。回声在全部完成之前不会呈现。我试过各种帖子的建议,但没有一个奏效。我的一些代码是: 有什么建议吗?谢了。

  • 问题内容: 该脚本未遍历“模块”数组的所有值。 这是运行的结果。该数组显示4个元素,但是.each黑色中的代码仅执行一次。 正在运行:打印消息[Module @ 71f09325,Module @ e1ddb41,Module @ 7069a674,Module @ 1f68f952]正在 运行:打印消息模块名称::::: puppetlabs-ntp正在 运行:打印消息安装非自定义正在 运行:工

  • 问题内容: 在下面的代码中,迭代运行两次。 是否可能恰好在第一次迭代和第二次迭代之间运行“ test2 <-true”? 我的意思是,在第一次迭代结束而第二次迭代未开始时,是否将true发送给“ test2”? 问题答案: 是。由于您的频道已缓冲,可以保存1个值。主执行流程可以继续进行,而无需您的匿名goroutine读取您发送到通道的值,并且可以在goroutine唤醒并读取通道上的值之前在通道

  • 如果格式不正确,请原谅,这是我的第一篇帖子。我想看看是否以前发现过这个问题,但我找不到任何人有与我相同的问题。 我试图学习Java,但我无法弄清楚为什么我的for循环没有输出最后一次迭代。我正在完成codeabbey的练习,并相对轻松地完成了前两个。然而,在第三个和第四个问题上,我无法在最后一次迭代中输出我的for循环。 我开始在谷歌上搜索,并想将我的答案与其他人的答案进行比较。当我的代码与我找到

  • 问题内容: 我正在使用SELECT语句从表中获取数据,然后将其插入到另一个表中。但是,行“ stmt.executeQuery(query);” 从表中插入第一行然后退出。当我注释掉这一行时,while循环遍历所有行,将它们打印出来。stacktrace没有显示任何错误。为什么会这样呢? 问题答案: 您将重新使用循环最后一行中产生的那个。 这将关闭 。如文档中所述: 阿当对象将自动关闭生成它对象被