简体   繁体   English

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

[英]python pipe limited to 196608 ( 65536*3 ) with subprocess.Popen()

I have this function call_external_command If len(data) <= 196608 it's ok, but if len(data) > 196608 it hang for ever. 我有此函数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]

Why this restriction ? 为什么会有这种限制? And How to work around ? 以及如何解决?

Oh great ! 太棒了 ! Indeed we have to use communicate() instead of stdin.write() : 实际上,我们必须使用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]

As oyu found out yourself, .communicate() handles this. 当oyu发现自己时, .communicate()处理此问题。

The reason for your observations are the following: 您进行观察的原因如下:

  • Two pipes connect your program and the subprocess, namely its stdin and its stdout. 两个管道连接程序和子进程,即其stdin和其stdout。
  • Depending on the OS, each of these pipes has a buffer size of 65536 bytes. 根据操作系统的不同,每个管道的缓冲区大小为65536字节。
  • Besides, depending on the program and what it does, it reads 65536 bytes as well and writes some data out. 此外,根据程序及其功能,它还读取65536字节并写出一些数据。

So, if you write 196608 bytes, the first 65536 bytes are sent to stdin, read by the program and (if it is cat , for example) output to the stdout pipe. 因此,如果您写入196608字节,则前65536字节将发送到stdin,由程序读取,并且(例如,如果它是cat )输出到stdout管道。 The second 65536 bytes are put to stdin, read by the program and tried to write to stdout, but there it blocks as stdout is full. 第二个65536字节放入stdin,由程序读取并尝试写入stdout,但由于stdout已满而在此处阻塞。 The third 65536 bytes are written to stdin. 第65536个字节的第三个字节被写入stdin。 For each excess byte, writing blocks because stdin is full as well. 对于每个多余的字节,写块是因为stdin也已满。

The solution is as you write: let .communicate() handle the whole thing. 解决方案就是您编写的过程:让.communicate()处理整个事情。 It is prepared for this situation and handles it, depending on the OS either with threading, poll or select calls. 根据操作系统的不同,可以通过线程,轮询或选择调用为这种情况做好准备并进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM