StringIO和BytesIO
你有没有过这种时候?只是想快速测试一段读写类文件的代码,但不想真的在项目根目录留临时文件?或者在 API 交互、数据管道处理时,要构造/解析一段完全不需要落地的字符串或二进制流?Python 的 io.StringIO 和 io.BytesIO 就是内存中的完美类文件流替身——它们继承自标准的 io.TextIOBase/io.BufferedIOBase 接口,但数据直接存在内存缓冲区里,省去了磁盘 I/O 的开销,API 却和真实磁盘文件几乎一致,代码可以在两种模式间无缝切换。
先搞清楚:什么时候用哪个?
两个类唯一的核心区别是数据的操作类型,选不对会直接报错(比如给 StringIO 写 bytes,给 BytesIO 写 str):
StringIO:纯文本流操作,只接受 Unicode 字符串(Python 3 的str),输出也是strBytesIO:二进制流操作,只接受字节序列(bytes或bytearray),输出也是字节类
上手 StringIO:内存中的文本缓冲区
基础玩法:创建+写入+读取
读取操作,完全像读文件一样:
其他实用方法(对应真实文件)
上手 BytesIO:内存中的二进制缓冲区
和 StringIO 几乎完全对应,但**所有操作换成字节相关就行:
- 写入时必须用
bytes/bytearray,Python 可以用b''前缀或者str.encode('utf-8')生成 - 读取时出来的是
bytes,要转文本用decode('utf-8') - getbuffer() 方法可以拿到只读的底层内存视图(避免复制数据,适合大二进制流处理)
基础玩法
读取+内存视图(高性能)
真实项目中的高频场景
- 单元测试模拟文件:比如测试一个读取 Excel 导出的函数,不需要真的生成 Excel 文件
- 网络API交互:比如用
requests库模拟上传文件时,直接传BytesIO对象 - 文本/二进制数据临时中转:比如爬虫爬取的压缩包解压前不需要存本地,直接在 BytesIO 里解压
- CSV/JSON/XML 临时生成/解析:比如临时生成一段 CSV 给前端,不需要落地
性能&最佳实践
性能小 tips
- 一般小到中量数据(比如几十MB以内)直接用
getvalue()/read()没问题 - 大二进制流(比如几百MB以上) 优先用
getbuffer()切片 - Python 3 的
io.StringIO/io.BytesIO比旧版的cStringIO/StringIO/BytesIO更快,别用旧模块了!
最佳实践
1. 用上下文管理器自动关闭
虽然内存缓冲区不需要像文件一样强制关闭(Python 垃圾回收会处理,但养成习惯+避免内存泄漏风险更好
2. 重用缓冲区
避免频繁创建销毁大对象
总结
io.StringIO 和 io.BytesIO 是 Python 标准库中非常实用的小工具:
- 完美模拟文件对象的完整接口
- 数据在内存中,速度快
- 避免了不必要的磁盘 I/O
- 代码可以在内存流和真实文件间无缝切换
下次再遇到“不想写文件/读文件,但要用文件接口”的场景,别犹豫,直接上它们!

