我需要从 HTTP 服务器获取一个 .tar.gz 存档并对它包含的每个文件执行 MD5sum。 由于存档压缩后为 4.5GB,解压后为 12GB,因此我想在不接触硬盘的情况下执行此操作。当然,我也不能将所有内容都保存在 RAM 中。
我正在尝试为此使用 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
最佳答案
即时查找远程存档中所有文件的 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)))
关于python - 流式传输大型远程压缩包内容的 md5sum,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27604420/