Python:有效地将大块字节连接成一个大块?

时间:2009-02-28 01:18:54

标签: python amazon-s3

我正试图对Amazon S3 python library进行评审,以允许对大文件进行分块处理。现在它做了一个“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 个答案:

答案 0 :(得分:3)

''join()是加入数据块的最佳方法。替代方案归结为重复串联,由于字符串的不变性以及在每个连接处创建更多的需要,这是O(n ** 2)。给定,这个重复的连接是通过最近版本的CPython优化的,如果与+ =一起使用成为O(n),但是这个优化只给它一个粗略的等价于'.join(),这显然是O(n)over字节数。

答案 1 :(得分:2)

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

因为通常你不想在内存中存储整个3Gb文件,所以我不会将这些块存储在一个数组中,而是遍历http_response并将其直接写入磁盘,使用正常文件在临时或永久文件中write()方法在适当的文件句柄上。

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

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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