【问题标题】:Reading/writing to a Popen() subprocess读取/写入 Popen() 子进程
【发布时间】:2012-04-28 13:18:26
【问题描述】:

我正在尝试使用 python subprocess.Popen() 调用与子进程交谈。在我的真实代码中,我正在实现一种 IPC,所以我想写入一些数据、读取响应、写入更多数据、读取响应等等。因此,我不能使用 Popen.communicate(),否则它适用于简单的情况。

这段代码显示了我的问题。它甚至从来没有得到第一个响应,挂在第一个“阅读结果”上。为什么?我怎样才能按预期完成这项工作?

import subprocess
p = subprocess.Popen(["sed", 's/a/x/g'],
                     stdout = subprocess.PIPE,
                     stdin = subprocess.PIPE)

p.stdin.write("abc\n")
print "Reading result:"
print p.stdout.readline()

p.stdin.write("cat\n")
print "Reading result:"
print p.stdout.readline()

【问题讨论】:

    标签: python subprocess popen python-2.6


    【解决方案1】:

    sed 的输出被缓冲,仅在累积足够多或输入流耗尽并关闭之前才输出其数据。

    试试这个:

    import subprocess
    p = subprocess.Popen(["sed", 's/a/x/g'],
                         stdout = subprocess.PIPE,
                         stdin = subprocess.PIPE)
    
    p.stdin.write("abc\n")
    p.stdin.write("cat\n")
    p.stdin.close()
    
    print "Reading result 1:"
    print p.stdout.readline()
    
    print "Reading result 2:"
    print p.stdout.readline()
    

    请注意,一旦缓冲区已满,写入stdin 的大量数据将无法可靠地完成此操作。最好的方法是使用communicate()

    【讨论】:

    • 但是当直接在 shell 中运行命令时,sed 不会那样做。如果你这样做,响应会出现在每一行之后。即使我在写完后调用 p.stdin.flush() ,问题仍然存在。此外,在现实生活中,我也编写了被调用程序,没有缓冲,它的行为方式相同。我不相信缓冲是这里的问题。
    • 添加 bufsize=0 可以解决您的问题。 subprocess.Popen(['sed', '-l', 's/a/x/g'], bufsize=0, stdin=PIPE, stdout=PIPE)
    【解决方案2】:

    如果可以的话,我会尝试使用Popen().communicate(),因为它为你做了很多好事,但是如果你需要完全按照你的描述使用Popen(),你需要设置sed来刷新它的缓冲区在带有 -l 选项的换行符之后:

    p = subprocess.Popen(['sed', '-l', 's/a/x/g'],
                         stdout=subprocess.PIPE,
                         stdin=subprocess.PIPE)
    

    你的代码应该可以正常工作

    【讨论】:

    • 确实有效!我的 sed 出于某种原因使用 -u 表示“无缓冲”,而不是 -l,但它的工作原理都是一样的。这解决了我的示例代码,但不幸的是不是我的真实代码,因为实际的命令不是 sed,而是另一个 python 程序。很好的回复,你指出了问题。
    • 是的,问题解决了。问题是结果的输出缓冲。在我的子进程中做一个简单的 stdout.flush() 解决了这个问题。谢谢!
    猜你喜欢
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    相关资源
    最近更新 更多