Python 3:使用'

时间:2017-07-07 21:08:07

标签: python python-3.x with-statement

我想做的是生成任意长度的字节流。原因是因为我需要基本上生成任意大小的文件。 (对于某些背景,我尝试流式传输稀疏文件,但是had trouble when the file sizes were large,所以我试图在运行中尝试生成字节。)

我一直在阅读文档以使对象与with一起使用,而且我正在努力做到这一点。这是我在经过反复试验后所尝试的内容,但仍然无效。我想我错过了什么,但说实话,我不知道是什么。

class BinaryGenerator:
    def __init__(self, size_in_mbs):
        self.size_in_mbs = size_in_mbs

    def __enter__(self):
        yield self.__bytes_generator__(self.size_in_mbs)
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    @staticmethod
    def __bytes_generator__(mega_bytes):
        for i in range(mega_bytes * 1024):
            yield b'\x00'

def __write_size__(size):
    with open('arbitrary-{}mb.bin'.format(size), 'wb') as file:
        with BinaryGenerator(size) as binary:
            file.write(binary)


if __name__ == '__main__':
    __write_size__(1)

我实际上将其与Requests Streaming Uploads一起使用,但我尝试将其用作测试,以查看是否可以复制使用{打开文件时获得的二进制数据流{1}}

1 个答案:

答案 0 :(得分:3)

记录

  • 当您有一个具有初始化和清理功能的对象时,使用context manager。在该示例中,它与文件对象一起使用。由于文件对象实现了上下文管理器协议,因此使用文件句柄退出with块将自动关闭该文件。

    with open('arbitrary-{}mb.bin'.format(size), 'wb') as fd: ...

  • a generator是(以编程方式)生成可迭代结果的函数。人们可以将其视为多次返回的函数。

至于你的问题:你可以使用生成器来实现结果流,这基本上就是它们的用途:

def bytes_generator(mega_bytes):
    for i in range(mega_bytes * 1024):
        yield b'\x00'

def write_size(size):
    with open('arbitrary-{}mb.bin'.format(size), 'wb') as fd:
         for b in bytes_generator(size):
              fd.write(b)
但是,这是非常低效的,因为它一次写入一个字节。但要修复它,您只需要修改生成器的分块。

Requests明确允许通过生成器进行分块上传。

def gen():
    yield 'hi'
    yield 'there'

requests.post('http://some.url/chunked', data=gen())