4

入力データのサイズがキロバイトからギガバイトに及ぶ可能性がある純粋なPythonパーサーに取り組んでいます。ファイルのようなオブジェクトをラップし、明示的な .open()/.seek()/.read()/.close() 呼び出しを単純なバッファのようなオブジェクトに抽象化するモジュールはありますか? これは、StringIO の逆と考えることができます。次のようになると思います。

with FileLikeObjectBackedBuffer(urllib.urlopen("http://www.google.com")) as buf:
    header = buf[0:0x10]
    footer = buf[-0x10:]

注、昨日同様mmapの質問をし、ファイルを受け入れました。ここでは、ファイルのようなオブジェクトをラップするモジュールを具体的に探しています (引数のために、 によって返されるもののように言いますurllib)。

更新 最初に質問して以来、この質問に繰り返し戻ってきましたurllibが、最良の例ではなかった可能性があります。ストリーミング インターフェイスであるため、これは少し特殊なケースです。より伝統的な//インターフェイスStringIObz2公開し、個人的にはこれらをより頻繁に使用します。したがって、ファイルのようなオブジェクトをバッファーとしてラップするモジュールを作成しました。ここで確認できます。seekreadclose

4

1 に答える 1

4

ファイルのような obj を返しますがurllib.urlopen、独自のものを書かずにやりたいことができるとは思いませんseek。たとえば、サポートしていませんがnext、サポートしていますreadなど...そして、転送を扱っているのでストリームのみ-特定のポイントに到達するまで取得し、バックトラッキングのためにキャッシュすることにより、ジャンプアヘッドを処理する必要があります。

IMHO-ネットワークIOストリームの一部を効率的にスキップすることはできません(最後のバイトが必要な場合でも、そこに到達するために以前のすべてのバイトを取得する必要があります-そのストレージを管理する方法はあなた次第です)。

あなたの以前の回答に従ってurlretrieve、ファイルに(または同様に)誘惑されます。mmap

サーバーが受け入れることができる場合ranges(そして応答サイズが既知であり、例に従ってその派生ブロックから)、可能な回避策はhttp://en.wikipedia.org/wiki/Byte_servingを使用することです(ただし、言うことはできません)私はそれを試したことがあります)。

例を考えると、最初の 16 と最後の 16 だけが必要で、「派手すぎる」ことをしたくない場合:

from string import ascii_lowercase
from random import choice
from StringIO import StringIO

buf = ''.join(choice(ascii_lowercase) for _ in range(50))
print buf

sio_buf = StringIO(buf) # make it a bit more like a stream object
first16 = sio_buf.read(16)
print first16

from collections import deque
last16 = deque(iter(lambda: sio_buf.read(1), ''), 16) # read(1) may look bad but it's buffered anyway - so...
print ''.join(last16)

出力:

gpsgvqsbixtwyakpgefrhntldsjqlmfvyzwjoykhsapcmvjmar
gpsgvqsbixtwyakp
wjoykhsapcmvjmar
于 2012-12-24T18:12:01.483 に答える