使用zstandard文件作为子进程输入输出时遇fileno属性缺失错误求方案
解决zstandard流与subprocess管道兼容问题
错误原因很明确:subprocess的stdin/stdout参数要求传入的对象必须具备fileno()方法(比如本地文件、系统管道、subprocess.PIPE),但zstandard.open()返回的是Python层面的压缩/解压流对象,没有这个系统级文件描述符属性,因此触发AttributeError。
下面提供两种实用解决方案:
方案1:用系统zstd命令构建管道(推荐)
直接借助系统自带的zstd命令处理压缩/解压,和目标进程串成管道链,完全利用操作系统的流式管道能力,内存占用极低,处理大文件效率最高,也符合Unix风格的管道用法。
import subprocess import zstandard # 生成测试用的压缩文件(仅示例,实际可直接用系统zstd命令生成) with zstandard.open('a.txt.zst', 'w') as f: f.write('hello\n') # 构建完整管道链:zstd解压 -> 目标进程(cat) -> zstd压缩 with open('a.txt.zst', 'rb') as input_file, open('b.txt.zst', 'wb') as output_file: # 第一步:解压输入文件到标准输出 decompress_proc = subprocess.Popen( ['zstd', '-d', '-c'], # -c表示输出到stdout stdin=input_file, stdout=subprocess.PIPE ) # 第二步:运行目标处理进程(这里用cat示例,实际替换为你的链式程序) target_proc = subprocess.Popen( ['cat'], stdin=decompress_proc.stdout, stdout=subprocess.PIPE ) # 第三步:将处理结果压缩后写入输出文件 compress_proc = subprocess.Popen( ['zstd', '-c'], stdin=target_proc.stdout, stdout=output_file ) # 等待所有进程执行完成 decompress_proc.wait() target_proc.wait() compress_proc.wait()
方案2:用Python线程中转流数据
如果必须依赖Python的zstandard库(比如需要自定义压缩参数、系统无zstd命令),可以通过线程中转Python流和子进程管道的数据,只要做好流的关闭和异常处理,完全可靠。
import subprocess import zstandard import threading def zstd_to_pipe(zstd_stream, pipe): """将zstandard流的数据写入子进程输入管道""" try: # 按1MB块读取,避免内存过载 while chunk := zstd_stream.read(1024 * 1024): pipe.write(chunk) finally: pipe.close() # 关闭管道,告知子进程输入结束 def pipe_to_zstd(pipe, zstd_stream): """从子进程输出管道读取数据,写入zstandard流""" try: while chunk := pipe.read(1024 * 1024): zstd_stream.write(chunk) finally: zstd_stream.close() # 确保压缩流写入完成并关闭 # 生成测试压缩文件 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') # 启动子进程,用PIPE连接输入输出 target_proc = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) # 启动两个线程分别处理输入和输出中转 thread_in = threading.Thread(target=zstd_to_pipe, args=(f_in, target_proc.stdin)) thread_out = threading.Thread(target=pipe_to_zstd, args=(target_proc.stdout, f_out)) thread_in.start() thread_out.start() # 等待子进程和线程完成 target_proc.wait() thread_in.join() thread_out.join()
内容的提问来源于stack exchange,提问作者d33tah
相关产品推荐
相关产品推荐

