3

Python 3 には、フィルタリング ストリームを作成するための構造がありますか? 特に、ここでの私の目標は、余分なコピーを作成することなく、REST サービスから読み取られたコンテンツの md5 チェックサムをリクエストで計算することです。ある種のフィルター ストリームをサブクラス化し、バイトを hashlib から派生した md5 オブジェクトに押し込むことができれば、それで十分です。

現在、私のコードには以下が含まれています:

shutil.copyfileobj(r.raw, outstream)

ここで、「r」は応答オブジェクトです。データの各バッファを読み取ったときに呼び出される r.raw の周りにジェネレータなどをラップして、それを md5 に渡すことができますか?

4

1 に答える 1

12

requestsURLデータをチャンクで読み取ることをサポートし、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()

于 2012-12-23T21:32:55.667 に答える