在Chunks中阅读RestResponse

时间:2014-07-29 00:02:02

标签: python python-2.7 dropbox-api

为了避免Python中的MemoryError,我试图读取块。一直在寻找半天如何从RestResponse读取块,但无济于事。

源是一个类似文件的对象,使用Dropbox SDK for python。

这是我的尝试:

import dropbox
from filechunkio import FileChunkIO
import math

file_and_metadata = dropbox_client.metadata(path)

hq_file = dropbox_client.get_file(file_and_metadata['path'])

source_size = file_and_metadata['bytes']
chunk_size = 4194304
chunk_count = int(math.ceil(source_size / chunk_size))
for i in range(chunk_count + 1):
    offset = chunk_size * i
    bytes = min(chunk_size, source_size - offset)
    with FileChunkIO(hq_file, 'r', offset=offset,
                 bytes=bytes) as fp:
        with open('tmp/testtest123.mp4', 'wb') as f:
            f.write(fp)
            f.flush()

这会导致“TypeError:强制转换为Unicode:需要字符串或缓冲区,找到RESTResponse”

非常感谢任何线索或解决方案。

1 个答案:

答案 0 :(得分:0)

在不了解FileChunkIO的情况下,甚至不知道代码在哪里引发异常,很难确定,但我的猜测是它需要一个真正的文件类对象。或者它可能会做一些愚蠢的事情,比如检查类型,以便它可以决定你是在寻找一个字符串还是一块文件。

无论如何,根据文档,RESTResponse不是一个完整的文件对象,但它实现了readclose。你可以轻松地实现read实现read的东西,而不需要任何花哨的包装器。当你到达EOF时,类文件对象的b''方法保证返回read,并且返回的字节数比你要求的少,所以你不需要猜测你需要多少次chunk_size = 4194304 with open('tmp/testtest123.mp4', 'wb') as f: while True: buf = hq_file.read(chunk_size) if not buf: break f.write(buf) 并在最后做一个简短的阅读。就这样做:

open

(注意我将chunk_size = 4194304 chunks = iter(lambda: hq_file.read(chunk_size), '') with open('tmp/testtest123.mp4', 'wb') as f: f.writelines(chunks) 移到了循环之外。否则,对于每个chunk,你将打开并清空文件,然后写下一个chunk,所以最后你会最后只有最后一个。)

如果你想要一个分块包装器,那么有一个非常好的内置函数iter可以为你做到:

''

请注意,如果您将b''更改为writelines,但完全相同的代码在Python 3.x中有效,但这会破坏Python 2.5。

这可能有点滥用partial(hq_file.read, chunk_size),因为我们正在编写一个实际上不是行的字符串的迭代。如果您不喜欢它,那么显式循环就会变得简单而简洁。

我通常把它写成lambda: hq_file.read(chunk_size_而不是{{1}},但这确实是一个偏好问题;阅读partial上的文档,你应该能够理解为什么它们最终具有相同的效果,并决定你喜欢哪一个。