python 3是否有用于制作过滤流的结构?特别是,我的目标是计算从REST服务读取的内容的md5校验和,而不需要额外的副本.如果我可以继承某种类型的过滤器流并将字节推送到hashlib派生的md5对象中,我会很好.
目前,我的代码包括:
shutil.copyfileobj(r.raw, outstream)
Run Code Online (Sandbox Code Playgroud)
其中'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())
Run Code Online (Sandbox Code Playgroud)
如果必须将其视为过滤器,请使用生成器:
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()
Run Code Online (Sandbox Code Playgroud)
然后在你的.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())
Run Code Online (Sandbox Code Playgroud)
因为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()
Run Code Online (Sandbox Code Playgroud)
该MD5TransparentFile()班需要你.iter_content()或.iter_lines()迭代器,并从每个调用返回的数据.read(),以及实时计算的MD5.这可以直接用于您的shutil.copyfileobj()示例.