2

我正在尝试对Amazon S3 python 库进行陪审,以允许对大文件进行分块处理。现在它执行“self.body = http_response.read()”,因此如果您有一个 3G 文件,您将在对其进行任何控制之前将整个内容读入内存。

我目前的方法是尝试保持库的接口相同,但在读取每个数据块后提供回调。类似于以下内容:

data = []
while True:
    chunk = http_response.read(CHUNKSIZE)
    if not chunk:
        break
    if callback:
        callback(chunk)
    data.append(chunk)

现在我需要做类似的事情:

self.body = ''.join(data)

加入是正确的方法还是有另一种(更好的)方法将所有块放在一起?

4

4 回答 4

3

''join() 是连接数据块的最佳方法。替代方案归结为重复连接,这是 O(n**2) 由于字符串的不变性和需要在每次连接时创建更多。鉴于,如果与 += 一起使用,这种重复的连接会被最新版本的 CPython 优化为 O(n),但这种优化只会给它一个粗略的等价于 ''.join() 反正,这明显是 O(n)字节数。

于 2009-02-28T01:24:44.827 回答
2

嗯 - 你想解决什么问题?我怀疑答案取决于您要对数据做什么。

由于通常您不希望将整个 3Gb 文件存储在内存中,因此我不会将块存储在数组中,而是遍历 http_response 并将其直接写入磁盘,使用普通 write() 在临时或持久文件中适当的文件句柄上的方法。

如果您确实想要内存中的数据的两个副本,那么您的方法将需要至少 6Gb 用于假设的 3Gb 文件,这对于大多数硬件来说可能很重要。我知道数组连接方法很快,但由于这是一个非常受内存限制的过程,也许你想找到一些更好的方法?StringIO ( http://docs.python.org/library/stringio.html ) 创建可以附加到内存中的字符串对象;纯python,因为它必须使用不可变字符串,所以只在内部使用你的数组连接技巧,但基于c的cStringIO实际上可能会附加到内部的内存缓冲区。我手头没有它的源代码,所以需要检查一下。

如果您确实希望对数据进行某种分析并且确实希望以最小的开销保存在内存中,您可能需要考虑使用 Numeric/NumPy 中的一些字节数组对象作为 StringIO 的替代方案。它们是针对大型数组优化的高性能代码,可能是您需要的。

作为一个有用的示例,对于具有内存高效迭代器友好方法的通用文件处理对象,您可能需要查看 django 文件对象块处理代码: http ://code.djangoproject.com/browser/django /trunk/django/core/files/base.py

于 2009-02-28T01:52:52.013 回答
1

在 python3 中,bytes对象与 不同str,但我不知道为什么会有任何问题。

于 2009-02-28T01:21:23.040 回答
0

join如果您确实需要将整个字符串放在一起似乎很好,但是无论如何您最终都会将整个字符串存储在 RAM 中。在这种情况下,我会尝试查看是否有办法处理字符串的每个部分,然后丢弃处理过的部分,因此您一次只需要在内存中保存固定数量的字节。这通常是回调方法的重点。(如果一次只能处理一部分块,请使用缓冲区作为队列来存储未处理的数据。)

于 2009-02-28T01:24:43.890 回答