You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExifTool批量待机模式下Python读取StdOut仅获65KB图像的问题

解决ExifTool保持打开模式下二进制输出读取不完整的问题

核心问题原因

你设置了universal_newlines=True(等价于Python3.7+的text=True),这个参数会让subprocess把所有标准流(stdin/stdout/stderr)都当作文本流处理,但-jpgfromraw -b输出的是二进制JPG数据,文本模式的流会对二进制数据做编码/解码处理,导致数据截断或损坏。

另外,ExifTool在-stay_open True模式下,每次执行完命令后会输出{ready}标记来表示准备接收下一条命令,你只读取一次固定大小的内容,自然拿不到完整的二进制数据。

正确实现方案

  1. 不要全局设置文本模式,而是单独给stdin指定编码(因为命令是文本),stdout保持二进制模式(默认就是)。
  2. 循环读取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:42:24