我需要运行一个使用 zstandard 文件(太大而无法放入内存)作为输入和输出的子进程管道。考虑以下示例:
import subprocess
import zstandard
with zstandard.open('a.txt.zst', 'w') as f:
f.write('hello\n')
f_in = zstandard.open('a.txt.zst', 'rb')
f_out = zstandard.open('b.txt.zst', 'wb')
# in reality I'd be running multiple programs here by chaining PIPEs, but first
# reads f_in and last writes to f_out:
subprocess.call(['cat'], stdin=f_in, stdout=f_out)
我收到以下错误:
Traceback (most recent call last):
File "/tmp/a.py", line 12, in <module>
subprocess.call(['cat'], stdin=f_in, stdout=f_out)
File "/usr/lib/python3.11/subprocess.py", line 389, in call
with Popen(*popenargs, **kwargs) as p:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/subprocess.py", line 892, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/subprocess.py", line 1661, in _get_handles
p2cread = stdin.fileno()
^^^^^^^^^^^^
AttributeError: 'zstd.ZstdDecompressionReader' object has no attribute 'fileno'
我正在考虑在两端使用管道并用线程供给它们,但感觉相当脆弱。这个问题有更惯用的解决方案吗?
subprocess.call
的stdin和stdout参数只能采用类似文件的对象,如果它具有有效的文件描述符(如here所述),因此当Python完成(解)压缩时,这将不起作用 - at系统级别没有包含解压数据的类似文件。
一般来说,从线程进行管道传输是一个很好的解决方案(特别是如果它可以帮助您避免临时文件),但在这里调用
zstdcat
作为链中的另一个程序可能更简单(用于输入,并且 zstd
具有正确的输出选项)。