requests 支持reading URL data in chunks,hashlib 库可以让您以块的形式计算 MD5,因此您已经拥有所需的一切。您可以在.iter_lines() 或.iter_content() 之间进行选择:
import requests
import hashlib
r = requests.get(url, stream=True)
sig = hashlib.md5()
for line in r.iter_lines():
sig.update(line)
print(sig.hexdigest())
如果您有将其视为过滤器,请使用生成器:
class MD5TransparentFilter:
def __init__(self, source):
self._sig = hashlib.md5()
self._source = source
def __iter__(self):
for line in self._source:
self._sig.update(line)
yield line
def hexdigest(self):
return self._sig.hexdigest()
然后在您的 .iter_lines() 或 .iter_content() 迭代器上使用它:
r = requests.get(url, stream=True)
filtered = MD5TransparentFilter(r.iter_content(1000))
for line in filtered:
# do something with the line
print(filtered.hexdigest())
对于shutil.copyfileobj(),您需要实现.read() 接口而不是.__iter__(),但原理相同:
class MD5TransparentFile:
def __init__(self, source):
self._sig = hashlib.md5()
self._source = source
def read(self, buffer):
# we ignore the buffer size, just use the `.next()` value in the source iterator
try:
line = self._source.next()
self._sig.update(line)
return line
except StopIteration:
return b''
def hexdigest(self):
return self._sig.hexdigest()
MD5TransparentFile() 类采用您的 .iter_content() 或 .iter_lines() 迭代器,并在每次调用 .read() 时从中返回数据,并即时计算 MD5。这可以直接用于您的shutil.copyfileobj() 示例。