我正在调用exiftool从5GB及以上的大型视频中提取描述的XMP标签。我的应用程序是Python,我看到一些耗尽内存的文件;我这样调用它:
fp = open('9502_UAS_2.mov', 'rb')
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -'
exiftool = subprocess.Popen(CMD.split(),
stdin=fp,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(json_bytes, stderr) = exiftool.communicate()
为了解决问题,我在CLI上尝试了变种。这表明从磁盘上的文件读取速度很快并且占用的RAM很少,而从STDIN读取(重新创建上面读取的文件指针)非常慢并且使用了大量RAM(我已经删除了输出JSON元数据)下面为了清楚起见):
time exiftool -api largefilesupport=1 -sort -a -S -G -struct -j 9502_UAS.mov
real 0m0.196s
time cat 9502_UAS.mov | exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -
real 0m33.514s
'顶部'显示第二个在这个5.1GB视频文件中消耗了高达1.4GB的RAM。
我想了解为什么从STDIN读取速度慢并消耗大量内存,因此我可以注意服务器上内存耗尽等限制。 exiftool是否按顺序读取整个STDIN流缓冲文件,直到它获得解析元数据所需的二进制信息?它不是寻求() - 前后找到它需要的东西吗?
相反,为什么如此快速地针对本机磁盘文件运行它? exiftool是否使用内存映射文件系统快速跳转到需要解析的文件部分?
理想情况下,我是从STDIN读取的,因为真正的应用程序的文件来源是AWS S3存储桶,如果可以避免,我不想将文件复制到本地AWS EC2磁盘,所以任何提高阅读效率的提示都会有所帮助。
感谢。
答案 0 :(得分:0)
嗯,您将整个内容传递给示例中的stdin
。当然,这需要时间。最好将文件名传递给外部工具:
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j {}'
exiftool = subprocess.Popen(CMD.format('9502_UAS_2.mov').split(),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
json_bytes, stderr = exiftool.communicate()
当传递给stdin
时,首先将整个文件传送到程序,并且只有在完成此过程后,该过程才会停止(无论工具是否已完成其工作)。
当文件位于远程服务器上时,您需要在该服务器上运行此脚本,将文件复制到本地文件,或者读取文件的第一个n
字节并仅将这些文件传递给exiftool。 (确定必须留下多大的n
作为练习......)