python 3是否具有制作过滤流的结构?特别是,我的目标是计算从带有请求的 REST 服务读取的内容的 md5 校验和,而无需制作额外的副本。如果我可以子类化某种过滤器流并将字节推入一个 hashlib 派生的 md5 对象,我会很好。
目前,我的代码包括:
shutil.copyfileobj(r.raw, outstream)
其中 'r' 是响应对象。我可以在 r.raw 周围包装一个生成器或一些类似的东西,它将在每个读取的数据缓冲区中调用,以便我可以将它传递给 md5?
python 3是否具有制作过滤流的结构?特别是,我的目标是计算从带有请求的 REST 服务读取的内容的 md5 校验和,而无需制作额外的副本。如果我可以子类化某种过滤器流并将字节推入一个 hashlib 派生的 md5 对象,我会很好。
目前,我的代码包括:
shutil.copyfileobj(r.raw, outstream)
其中 'r' 是响应对象。我可以在 r.raw 周围包装一个生成器或一些类似的东西,它将在每个读取的数据缓冲区中调用,以便我可以将它传递给 md5?
requests
支持以块的形式读取 URL 数据,并且该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()
示例。