ExifTool批量待机模式下Python读取StdOut仅获65KB图像的问题
解决ExifTool保持打开模式下二进制输出读取不完整的问题
核心问题原因
你设置了universal_newlines=True(等价于Python3.7+的text=True),这个参数会让subprocess把所有标准流(stdin/stdout/stderr)都当作文本流处理,但-jpgfromraw -b输出的是二进制JPG数据,文本模式的流会对二进制数据做编码/解码处理,导致数据截断或损坏。
另外,ExifTool在-stay_open True模式下,每次执行完命令后会输出{ready}标记来表示准备接收下一条命令,你只读取一次固定大小的内容,自然拿不到完整的二进制数据。
正确实现方案
- 不要全局设置文本模式,而是单独给stdin指定编码(因为命令是文本),stdout保持二进制模式(默认就是)。
- 循环读取stdout内容,直到遇到ExifTool的
{ready}标记,分离出二进制图像数据和标记。
修正后的代码
import subprocess # 启动保持打开的ExifTool进程 proc = subprocess.Popen( ['exiftool', "-stay_open", "True", "-@", "-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', # 仅stdin用文本编码,stdout/stderr默认二进制 errors='ignore' ) # 构造提取预览图的命令(每行一个参数) exiftool_args = [ '-b', '-jpgfromraw', '-o', '-', # 输出到stdout '/Volumes/RAM Disk/0204.NEF', '-execute' ] # 把命令转为换行分隔的文本,写入stdin proc.stdin.write('\n'.join(exiftool_args) + '\n') proc.stdin.flush() # 读取输出:直到收到{ready}标记 output_data = b'' while True: chunk = proc.stdout.read(4096) if not chunk: break # 检查是否包含{ready}标记 ready_idx = chunk.find(b'{ready}') if ready_idx != -1: # 分离图像数据和标记 output_data += chunk[:ready_idx] break output_data += chunk # 保存图像 with open('/Volumes/RAM Disk/01.jpg', 'wb') as out_file: out_file.write(output_data) # 如果不需要继续处理,关闭ExifTool proc.stdin.write('-stay_open\nFalse\n') proc.stdin.flush() proc.wait()
关键细节说明
- 流模式分离:通过
encoding='utf-8'让stdin以文本模式处理命令,stdout保持二进制模式处理图像数据,避免编码冲突。 - 读取逻辑:循环读取stdout,直到找到
{ready}标记,确保拿到完整的二进制图像数据,而不是只读取固定大小的内容。 - 命令格式:ExifTool的
-@ -模式要求每个参数单独一行,最后必须加-execute触发执行。
内容的提问来源于stack exchange,提问作者LoneVort
相关产品推荐
相关产品推荐

