Python 流式MD5大型远程tarball的内容总和

Python 流式MD5大型远程tarball的内容总和,python,Python,我需要从HTTP服务器获取一个.tar.gz归档文件,并对其中包含的每个文件执行MD5sum。 由于归档文件是4.5GB压缩的,12GB解压缩的,所以我希望这样做时不接触硬盘。当然,我也不能把所有的东西都放在内存中 我正试图使用python实现它,但我的问题是,出于某种奇怪的原因,tarfile模块试图将seek()搜索到输入文件句柄的末尾,这是管道流无法做到的。想法 import tarfile import hashlib import subprocess URL = 'http://my

我需要从HTTP服务器获取一个.tar.gz归档文件,并对其中包含的每个文件执行MD5sum。 由于归档文件是4.5GB压缩的,12GB解压缩的,所以我希望这样做时不接触硬盘。当然,我也不能把所有的东西都放在内存中

我正试图使用python实现它,但我的问题是,出于某种奇怪的原因,tarfile模块试图将seek()搜索到输入文件句柄的末尾,这是管道流无法做到的。想法

import tarfile
import hashlib
import subprocess
URL = 'http://myhost/myfile.tar.gz'

url_fh = subprocess.Popen('curl %s | gzip -cd' % URL, shell=True, stdout=subprocess.PIPE)
tar_fh = tarfile.open(mode='r', fileobj=url_fh.stdout)
for tar_info in tar_fh:
    content_fh = tar_fh.extractfile(tar_info)
    print hashlib.md5(content_fh.read()).hexdigest(), tar_info.name
tar_fh.close()
上述操作失败,原因如下:

Traceback (most recent call last):
  File "gzip_pipe.py", line 13, in <module>
    tar_fh = tarfile.open(mode='r', fileobj=url_fh.stdout)
  File "/algo/algos2dev4/AlgoOne-EC/third-party-apps/python/lib/python2.6/tarfile.py", line 1644, in open
    saved_pos = fileobj.tell()
IOError: [Errno 29] Illegal seek
回溯(最近一次呼叫最后一次):
文件“gzip_pipe.py”,第13行,在
tar\u fh=tarfile.open(mode='r',fileobj=url\u fh.stdout)
文件“/algo/algos2dev4/AlgoOne EC/third party apps/python/lib/python2.6/tarfile.py”,第1644行,打开
已保存的\u pos=fileobj.tell()
IOError:[Errno 29]非法搜索

要动态查找远程存档中所有文件的md5总和,请执行以下操作:

#!/usr/bin/env python
import tarfile
import sys
import hashlib
from contextlib import closing
from functools import partial

try:
    from urllib.request import urlopen
except ImportError: # Python 2
    from urllib2 import urlopen

def md5sum(file, bufsize=1<<15):
    d = hashlib.md5()
    for buf in iter(partial(file.read, bufsize), b''):
        d.update(buf)
    return d.hexdigest()

url = sys.argv[1] # url to download
with closing(urlopen(url)) as r, tarfile.open(fileobj=r, mode='r|*') as archive:
    for member in archive:
        if member.isreg(): # extract only regular files from the archive
            with closing(archive.extractfile(member)) as file:
                print("{name}\t{sum}".format(name=member.name, sum=md5sum(file)))
#/usr/bin/env python
导入tarfile
导入系统
导入hashlib
从上下文库导入关闭
从functools导入部分
尝试:
从urllib.request导入urlopen
除此之外:#Python 2
从urllib2导入urlopen

def md5sum(file,bufsize=1因为tarfile模块试图查找()的某些奇怪原因到输入文件句柄的末尾。实际上不是。但它确实需要使用seek来查找文件对象中的各种记录。错误表明
TarFile
对象只是试图记录当前的读取位置,以便在发生错误时可以将文件对象返回到其初始状态。@martijnPieters I d在bash
curl中,我无法理解它http://myhost/myfile.tar.gz |tar-xz
可以在不寻求结束的情况下工作;难道不能在Python中复制相同的东西吗?在这种情况下,
tar
命令在磁盘上创建一个本地缓冲区IIRC。Python tar模块不适用于该用例,不需要。curl | tar-xz不需要等待t他需要下载5GB的文件,然后才能开始将其解压缩为单个文件…是的,当然。但这并不意味着它不会使用本地缓冲区。