6

urllibからのhttp応答があります

response = urllib2.urlopen('http://python.org/')

seek()最終的には、応答の範囲内で(少なくとも最初まで)できるようにしたいと思います。だから私はこのようなコードを持つことができるようにしたいと思います:

print result.readline()
result.seek(0)
print result.readline()

この問題の最も簡単な解決策はStringIOio.BytesIO 次のとおりです。

result = io.BytesIO(response.read())

ただし、要求したいリソースは非常に大きくなる傾向があり、ダウンロード全体が完了する前にそれらのリソースで作業を開始したい(解析...)ということです。response.read()ブロッキングしています。ノンブロッキングソリューションを探しています。

理想的なコードはread(BUFFER_SIZE)リソースからのものであり、より多くのコンテンツが必要な場合はいつでも、応答からより多くを要求するだけです。私は基本的にそれを行うことができるラッパークラスを探しています。ああ、オブジェクトのようなファイルが必要です。

私は次のようなものを書くことができると思いました:

base = io.BufferedIOBase(response)
result = io.BufferedReader(base)

ただし、これは機能しないことが判明し、ioモジュールとは異なるクラスを試しましたが、機能させることができませんでした。目的の動作をするラッパークラスに満足しています。

4

2 に答える 2

1

データの最初のチャンクを保持する独自のラッパー クラスを作成しました。このようにして、最初に戻ってエンコーディング、ファイルの種類などを分析できます。このクラスは私の問題を解決し、他のユースケースに適応するのに十分なほど単純でなければなりません。

class BufferedFile(object):
    ''' A buffered file that preserves the beginning of a stream up to buffer_size
    '''
    def __init__(self, fp, buffer_size=1024):
        self.data = cStringIO.StringIO()
        self.fp = fp
        self.offset = 0
        self.len = 0
        self.fp_offset = 0
        self.buffer_size = buffer_size

    @property
    def _buffer_full(self):
        return self.len >= self.buffer_size

    def readline(self):
        if self.len < self.offset < self.fp_offset:
            raise BufferError('Line is not available anymore')
        if self.offset >= self.len:
            line = self.fp.readline()
            self.fp_offset += len(line)

            self.offset += len(line)

            if not self._buffer_full:
                self.data.write(line)
                self.len += len(line)
        else:
            line = self.data.readline()
            self.offset += len(line)
        return line

    def seek(self, offset):
        if self.len < offset < self.fp_offset:
            raise BufferError('Cannot seek because data is not buffered here')
        self.offset = offset
        if offset < self.len:
            self.data.seek(offset)
于 2013-01-04T22:26:00.547 に答える
-1

Requestsライブラリを使用すると、ストリーミングされている応答を反復処理できます。

Twitter ストリーミング API を使用してキーワード「リクエスト」を追跡するには:

import requests
import json

r = requests.post('https://stream.twitter.com/1/statuses/filter.json',
    data={'track': 'requests'}, auth=('username', 'password'), stream=True)

for line in r.iter_lines():
    if line: # filter out keep-alive new lines
        print json.loads(line)

シークできるようにするには、既に反復 (読み取り) したデータを保存する必要があります。

于 2013-01-04T19:48:15.147 に答える