在内存中生成一个大文件,并将其流式传输到对象存储中

时间:2018-08-28 18:54:44

标签: python

我正在尝试对openstack swift对象存储进行一些负载测试,并希望查看大文件的传输和失败率。如何生成一个大的0s文件,并将其作为生成的文件流传输到某个地方?

在bash中,我会做类似

的操作
dd if=/dev/zero | aws s3 cp - s3://destination/thing

从磁盘读取文件的示例

with open("test.png", "rb") as f:
  client.put_object("default", "photos/my_copy_of_test.png", f.read())

1 个答案:

答案 0 :(得分:2)

put_object方法需要bytes或文件对象。

在现有代码中,由于某种原因,您传递的是f.read()而不是f,这意味着您是将整个文件读入内存,然后传递字节。如果文件数据可以接受,那么内存数据当然可以接受,因此您可以构建一个大的bytes并传递它。

如果您不想提前构建整个缓冲区,则需要创建一个文件对象,该文件对象会在使用者调用read函数之一时按需生成字节。

在Python 3中,实现此目的的方法是创建一个实现io.RawIOBaseio.BufferedIOBase的类。从the docs中可以看到,要做到这一点,您只需要提供几种方法,其余方法将自动为您生成。


原始I / O更简单。您需要编写的主要方法是readinto。您将被传递一个bytearray(或其他类似bytes的可变对象),并期望尽可能多地填充它。因此,您的班级可能看起来像这样:

class StreamingFile(io.RawIOBase):
    def readinto(self, b):
        buf = generate_raw_bytes(len(b))
        b[:len(buf)] = buf
        return len(buf)

(很明显,如果您可以编写generate_raw_bytes函数来直接在b中生成数据,而不是将其复制过来,则效率会更高。)

put_object方法实际上可能会调用其他文件方法,例如readreadline,readlines , iter {{ 1}} RawIOBase , etc., but that's fine;读入`。


如果您无法精确控制生成的字节数怎么办?您一次只能创建一条线,即使您只要求输入40条,该行的范围也可以是1字节到300。然后,您要使用内部缓冲区。您仍然可以使用automatically gives you implementations of all of those methods in terms of your来做到这一点,但是最好改为实现RawIOBase并定义readread1方法。