Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么我的Popen管会堵塞?_Python_Subprocess_Pipe - Fatal编程技术网

Python 为什么我的Popen管会堵塞?

Python 为什么我的Popen管会堵塞?,python,subprocess,pipe,Python,Subprocess,Pipe,我试图将一些数据提供给一系列相互连接的进程 通过管道。然而,我无法关闭它 p1 = subprocess.Popen("sort", stdin=subprocess.PIPE, stdout=subprocess.PIPE) p2 = subprocess.Popen("uniq", stdin=p1.stdout, stdout=subprocess.PIPE) p1.communicate(r""" a b c a""") out, _ = p2.communicate() print(

我试图将一些数据提供给一系列相互连接的进程 通过管道。然而,我无法关闭它

p1 = subprocess.Popen("sort", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p2 = subprocess.Popen("uniq", stdin=p1.stdout, stdout=subprocess.PIPE)

p1.communicate(r"""
a
b
c
a""")
out, _ = p2.communicate()
print(out)
程序现在只是在等待。是否有其他方法可以向p1发出输入结束的信号


--注意:我正在windows上运行

您需要在第一个程序上关闭stdin

需要注意的一些事项:

  • 管道之间存在缓冲区(subprocess.PIPE为您创建的内容),缓冲区的大小因平台和用途而异。现在还不必担心这一点,因为它不像:

  • 特别是在这种情况下,
    sort
    需要在能够排序之前读取完整的输入(如果您还不知道它们是什么,则无法排序)

  • 由于
    2
    ,它有自己的缓冲区,用于收集并等待文件描述符关闭,表示已完成;)

    编辑:这是我举的一个例子。我个人认为直接使用管道更干净,因为您可以在生成流程之前单独构建输入:

    In [2]: import os
       ...: import subprocess
       ...: 
       ...: # A raw os level pipe, which consists of two file destriptors
       ...: # connected to each other, ala a "pipe".
       ...: # (This is what subprocess.PIPE sets up btw, hence it's name! ;)
       ...: read, write = os.pipe()
       ...: 
       ...: # Write what you want to it. In python 2, remove the `b` since all `str`ings are `byte` strings there.
       ...: os.write(write, b"blahblahblah")
       ...: 
       ...: # Close stdin to signal completion of input
       ...: os.close(write)
       ...: 
       ...: # Spawn process using the pipe as stdin
       ...: p = subprocess.Popen(['cat'], stdin=read)
       ...: 
    blahblahblah
    

    另外,请确保您
    p.wait()
    等待流程的完成,否则您可能会遇到尚未获得完整结果的情况。

    免责声明:这里不是专家。我以前没有使用过
    communicate()
    ,但是

    首先,在读取时,它意味着从正在运行的进程的stdout/stderr中读取数据:

    从stdout和stderr读取数据

    因此,我猜
    p1
    执行
    sort
    的输出会被python程序读取。或者更准确地说,在我的Linux机器上,行为似乎不是确定性的——有时是Python代码,有时是读取
    p1/sort
    标准输出的
    p2/uniq
    。我猜他们只是在争夺数据

    看起来
    communicate()
    是一种组合,对于您的用例(使用
    p1/sort
    )来说,它做得有点太多了。使用
    p2/uniq也可以


    另一方面,如果您尝试:

    import subprocess
    
    p1 = subprocess.Popen("sort", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    p2 = subprocess.Popen("uniq", stdin=p1.stdout, stdout=subprocess.PIPE)
    
    p1.stdin.write(r"""
    a
    b
    c
    a""")
    p1.stdin.close()
    out, _ = p2.communicate()
    print(out)
    
    它似乎起作用了。

    FWIW(在Linux上运行)该程序确实结束了(而且大部分时间不打印任何内容)