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暴露一个更传统的seek//接口readclose我个人使用这些比较频繁。因此,我编写了一个将类文件对象包装为缓冲区的模块。你可以在这里查看

4

1 回答 1

4

虽然urllib.urlopen返回一个类似文件的 obj,但我不相信不编写自己的文件就可以做你想做的事 -seek例如,它不支持,但支持next等等read......而且因为你正在处理一个 forward只有流 - 您必须通过检索来处理跳转,直到您到达某个点并缓存任何回溯。

恕我直言 - 您无法有效地跳过网络 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 回答