池.map4次迭代后挂起

2024-09-29 01:31:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我是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倍。这个“4”有什么神奇之处,我做错了什么?在


Tags: importcmdmap进程osloggingstderrsys
1条回答
网友
1楼 · 发布于 2024-09-29 01:31:36

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

解决方案是使用subprocess.call这样的函数对要运行的代码执行完整的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块,然后挂在最后一块之后

^{pr2}$

相关问题 更多 >