使Python内置流包装器不关闭基础BytesIO

时间:2019-06-27 12:53:31

标签: python python-3.7

我正在将内存文件创建为io.BytesIO对象。

文件内容是使用顶部的各种内置Python包装器创建的,例如io.TextIOWrappercsv.DictWriter(仅作为示例,我使用了更多的Python stdlib):

def generate_file():
    raw_bytes = io.BytesIO()
    with io.TextIOWrapper(raw_bytes, encoding='utf-8') as wrapper:
        writer = csv.DictWriter(wrapper, ["a", "b", "c"])
        writer.writeheader()
    return raw_bytes

此方法失败了,因为TextIOWrapper将关闭其基础流=我们的raw_bytes

generate_file().seek(0)

ValueError: I/O operation on closed file.

根据https://bugs.python.org/issue21363,缓冲区可以被分离,但这无济于事,因为上下文管理器会引发另一个错误:

def generate_file():
    raw_bytes = io.BytesIO()
    with io.TextIOWrapper(raw_bytes, encoding='utf-8') as wrapper:
        writer = csv.DictWriter(wrapper, ["a", "b", "c"])
        writer.writeheader()
        wrapper.detach()
    return raw_bytes

generate_file().seek(0)

ValueError: underlying buffer has been detached

我找到了两种解决方案:

  1. 部分hack:不使用上下文管理器,则上述方法有效(上下文管理器不会尝试访问分离的对象)。

  2. 一般技巧:使BytesIO忽略任何close()调用:

class NonClosingBytesIO(io.BytesIO):

    def close(self):
        pass


def generate_file():
    raw_bytes = NonClosingBytesIO()
    with io.TextIOWrapper(raw_bytes, encoding='utf-8') as wrapper:
        writer = csv.DictWriter(wrapper, ["a", "b", "c"])
        writer.writeheader()
    return raw_bytes

generate_file().getvalue()

b'a,b,c\r\n'

问题:这样安全吗?您能提出更好(更清洁)的解决方案吗?

0 个答案:

没有答案