如何正确关闭两个进程共享的管道?

2024-09-28 03:24:08 发布

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

我尝试使用管道在python中的进程之间进行通信。这些进程将从不同的线程调用,因此可能无法直接访问每个进程的Popen对象。我写了下面的脚本,作为一个简单的概念证明,但我发现我的接收过程永远不会终止。在

import os
import subprocess
import traceback
import shlex


if __name__ == '__main__':
    (fd_out, fd_in) = os.pipe()
    pipe_in = os.fdopen(fd_in, 'w')
    pipe_out = os.fdopen(fd_out, 'r')
    file_out = open('outfile.data', 'w+')

    cmd1 = 'cat ' + ' '.join('parts/%s' % x for x in sorted(os.listdir('parts')))
    cmd2 = 'pbzip2 -d -c'
    pobj1 = subprocess.Popen(shlex.split(cmd1), stdout=pipe_in)
    pobj2 = subprocess.Popen(shlex.split(cmd2), stdin=pipe_out,
                                                stdout=file_out)


    print 'closing pipe in'                                                     
    pipe_in.close()                                                             
    print 'closing pipe out'                                                    
    pipe_out.close()                                                            
    print 'closing file out'                                                    
    file_out.close()                                                            
    print 'waiting on process 2'                                                
    pobj2.wait()                                                                
    print 'done'        

这在很多方面都是正确的。数据块通过管道传输到第二个进程,第二个进程解压流并将其写入文件。我可以观察进程,直到它们看起来只是在等待(什么也不做),终止第二个进程,文件似乎已经完全写入。在

所以,我想知道为什么第二个进程永远不会终止。它似乎从未意识到输入流已经关闭。如何正确关闭管道,以便进程知道终止?在

^{pr2}$

我想我在做一些蠢事。我想知道是什么,为什么。在


Tags: inimportclose管道进程osoutfile
2条回答

使用subprocess.Popen(),您不需要手动调用os.pipe()之类的事情。在

pobj1 = subprocess.Popen(['cat'] + ['parts/' + x for x in sorted(os.listdir('parts'))],
                         stdout=PIPE)
pobj2 = subprocess.Popen(shlex.split('pbzip2 -d -c'),
                         stdin=pobj1.stdout,
                         stdout=open('outfile.data', 'w+'))

应该做你想做的。在

第二个进程可能是继承管道的输入端,因此管道永远不会关闭。我不是Python专家,但也许可以通过Popen首先使用stdin=PIPE对第二个进程进行Popen,然后使用第二个进程的.stdin作为其stdout,来避免这一问题。(Popen可能会安排进程在内部创建的管道的输入端没有句柄。)

为了解决文件描述符继承问题,请使用close_fds=True调用子进程:

pobj2 = subprocess.Popen(shlex.split(cmd2),
                         stdin=pipe_out,
                         stdout=file_out,
                         close_fds=True)

相关问题 更多 >

    热门问题