带有subprocess.Popen()的python管道限制为196608(65536 * 3)

时间:2018-12-22 13:06:32

标签: python pipe

我有此功能call_external_command如果len(data)<= 196608可以,但是如果len(data)> 196608则可以永久挂起。

def call_external_command(command, data):
    try:
        p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
        p.stdin.write(data)
    except:
        return None
    else:
        return p.communicate()[0]

为什么有此限制?以及如何解决?

2 个答案:

答案 0 :(得分:0)

哦,太好了!实际上,我们必须使用communicate()而不是stdin.write()

def call_external_command(command, data):
    p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
    return p.communicate(data)[0]

答案 1 :(得分:0)

当oyu发现自己时,.communicate()会处理这个问题。

您进行观察的原因如下:

  • 两个管道连接程序和子进程,即其stdin和其stdout。
  • 根据操作系统的不同,每个管道的缓冲区大小为65536字节。
  • 此外,根据程序及其功能,它还读取65536字节并写出一些数据。

因此,如果您写入196608字节,则将前65536字节发送到stdin,由程序读取,并(例如,如果为cat)输出到stdout管道。第二个65536字节放入stdin,由程序读取并尝试写入stdout,但由于stdout已满而在此处阻塞。第65536个字节的第三个字节被写入stdin。对于每个多余的字节,写块是因为stdin也已满。

解决方案就如您所写:让.communicate()处理整个事情。根据这种情况,可以通过线程,轮询或选择调用为这种情况做好准备并进行处理。