主要观点:在 Python 中,若需内存中存储字节的类文件对象,可使用io.BytesIO()
。读取数据时若数据量较大,应节省内存,文中涵盖BytesIO
的介绍、BytesIO.read()
的内存使用影响、高效访问BytesIO
数据的两种替代方法及权衡。
关键信息:
io.BytesIO
可创建内存中存储字节的类文件对象,如f = BytesIO()
,可写入字节并通过f.read()
读取。BytesIO.read()
在一次性读取所有数据时会使内存使用量翻倍,如通过测量函数可看出。BytesIO.getbuffer()
返回底层数据的memoryview
,不分配新内存,如data : memoryview = f.getbuffer()
,但memoryview
缺少bytes
的某些方法,且从编译扩展访问memoryview
对象有问题,从memoryview
创建新bytes
对象会复制数据。BytesIO.getvalue()
返回BytesIO
的内容作为bytes
对象,神奇的是不分配内存,利用了写时复制,如data : bytes = f.getvalue()
,写入时才会分配新内存。
重要细节:- 测量内存使用的函数
report_allocated
通过gc.collect()
收集垃圾,tracemalloc.get_traced_memory()
获取内存使用情况。 memoryview
在 CPython 3.11 及之后版本的稳定 C ABI 中可正常访问,当前多数开源项目支持 3.10 和 3.9 版本,在这些版本中从编译扩展访问memoryview
有问题。- 实际应用中,从
read()
切换到getvalue()
可节省内存,如在Polars 的 pull request中有所体现。总结:提取BytesIO
数据时,避免BytesIO.read()
(除非多次小读),需要所有内容为bytes
用BytesIO.getvalue()
,可用memoryview
时用BytesIO.getbuffer()
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。