【问题标题】:python on-the-fly md5 as one reads a streampython on-the-fly md5 作为一个读取流
【发布时间】:2020-03-06 23:00:50
【问题描述】:

python 3 有用于制作过滤流的结构吗?特别是,我的目标是计算从带有请求的 REST 服务读取的内容的 md5 校验和,而无需制作额外的副本。如果我可以子类化某种过滤器流并将字节推入一个 hashlib 派生的 md5 对象,我会很好。

目前,我的代码包括:

shutil.copyfileobj(r.raw, outstream)

其中 'r' 是响应对象。我可以在 r.raw 周围包装一个生成器或其他类似的东西,它将在每个数据缓冲区被读取时调用,以便我可以将它传递给 md5?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    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() 示例。

    【讨论】:

      猜你喜欢
      • 2011-10-22
      • 2018-06-16
      • 1970-01-01
      • 2021-06-10
      • 2023-03-06
      • 1970-01-01
      • 2019-08-05
      • 2010-12-18
      • 2016-02-06
      相关资源
      最近更新 更多