Python 的子进程 returns 在使用 PIPE 读取非常长的输出时截断了输出

Python's sub-process returns truncated output when using PIPE to read very long outputs

我们有一个在 NodeJS 中开发的光栅化实用程序,可将 HTML 字符串转换为呈现的 HTML 页面的 Base64。我们使用它的方式是使用子进程模块 运行 实用程序,然后使用 PIPE 读取其 STDOUT。实现这个的基本代码如下:

    from subprocess import run, PIPE
    result = run(['capture', tmp_file.name, '--type', 'jpeg'], stdout=PIPE, stderr=PIPE, check=True)
    output = result.stdout.decode('utf-8')

输出包含呈现的 HTML 页面的 Base64 字符串。由于 Base64 对于大页面来说非常大,我注意到对于某些 HTML 页面,输出是 t运行cated 并且不完整。但是,这是随机发生的,因此 Base64 一次可能对页面正确,但下一次 t运行cated。重要的是要在这里提到,我目前正在使用线程(10 个线程)同时将 HTML 转换为 Base64 图像,因此它可能在这里发挥作用。

我对此进行了详细分析,发现在幕后,subprocess.run 方法使用 _communicate 方法,而后者又使用 os.read() 方法从 PIPE 中读取。我打印了它的输出,发现它也是 t运行cated,这就是为什么 STDOUT 是 t运行cated。完全奇怪的行为。

最后,我能够通过使用文件句柄而不是 PIPE 来解决这个问题,而且效果很好。

with open(output_filename, 'w+') as out_file:
    result = run(['capture', tmp_file.name, '--type', 'jpeg'], stdout=out_file, stderr=PIPE, check=True)

我很好奇为什么 PIPE 无法处理完整的输出,而且是随机的。

当您 运行 子进程时,命令在 bash 上执行。 当您使用 PIPE 作为标准输出时,内部 bash 将数据存储在临时变量中,该变量的硬限制为 128 Kb。超过 128kb 的任何内容都会被处理运行。

处理大数据的最佳方法是捕获文件中的输出。