我正在将内存文件创建为io.BytesIO
对象。
文件内容是使用顶部的各种内置Python包装器创建的,例如io.TextIOWrapper
或csv.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
我找到了两种解决方案:
部分hack:不使用上下文管理器,则上述方法有效(上下文管理器不会尝试访问分离的对象)。
一般技巧:使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'
问题:这样安全吗?您能提出更好(更清洁)的解决方案吗?