第六章 文件类模块
本文主要介绍和文件相关的模块,包括文件类型csv、json、xml,文件模拟在内存中创建的
StringIO,数据的序列化与反序列化,以及最常见的上下文管理器with。
csv 模块:读写 CSV 文件用于处理 逗号分隔值(Comma-Separated Values) 文件,常用于表格数据导入导出。
import csv
# 写入列表数据
with open('data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['Name', 'Age', 'City']) # 表头
writer.writerow(['Alice', 30, 'New York'])
writer.writerows([['Bob', 25, 'London'], ['Charlie', 35, 'Tokyo']])
# 写入字典数据(推荐)
with open('data_dict.csv', 'w', newline='', encoding='utf-8') as f:
fieldnames = ['Name', 'Age', 'City']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'Name': 'Alice', 'Age': 30, 'City': 'New York'})
# 读取为列表
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row) # ['Alice', '30', 'New York']
# 读取为字典(推荐)
with open('data_dict.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
print(row['Name'], row['Age']) # Alice 30
✅ 注意:
- 使用
newline=''避免空行(Windows)- 指定
encoding='utf-8'防止中文乱码
json 模块:处理 JSON 数据用于 序列化/反序列化 JSON(JavaScript Object Notation),是 Web API 和配置文件的通用格式。
import json
data = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "coding"],
"active": True,
"balance": None
}
# 序列化:Python → JSON 字符串
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
# 反序列化:JSON 字符串 → Python
parsed = json.loads(json_str)
print(parsed['name']) # Alice
# 写入 JSON 文件
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 读取 JSON 文件
with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
🔑 参数说明:
ensure_ascii=False:支持中文indent=2:美化输出(适合人类阅读)sort_keys=True:按键排序
⚠️ 限制: JSON 不支持
set、datetime、自定义类等类型。需自定义default函数或预处理。
xml 处理:使用
xml.etree.ElementTreePython 标准库提供轻量级 XML 解析器( 不验证 DTD/XSD)。
import xml.etree.ElementTree as ET
xml_data = '''
<bookstore>
<book id="1">
<title>Python指南</title>
<author>张三</author>
<price>59.9</price>
</book>
<book id="2">
<title>数据科学实战</title>
<author>李四</author>
<price>79.9</price>
</book>
</bookstore>
'''
# 从字符串解析
root = ET.fromstring(xml_data)
# 或从文件解析
# tree = ET.parse('books.xml')
# root = tree.getroot()
# 遍历
for book in root.findall('book'):
title = book.find('title').text
author = book.find('author').text
price = float(book.find('price').text)
book_id = book.get('id') # 获取属性
print(f"ID:{book_id} | {title} by {author} - ¥{price}")
# 创建根元素
root = ET.Element("students")
# 添加子元素
student = ET.SubElement(root, "student", id="101")
ET.SubElement(student, "name").text = "王五"
ET.SubElement(student, "grade").text = "A"
# 写入文件
tree = ET.ElementTree(root)
tree.write("students.xml", encoding="utf-8", xml_declaration=True)
✅ 优点:内存占用小(适合大文件) ❌ 缺点:功能有限,复杂场景建议用
lxml(第三方库)
io.StringIO /
io.BytesIO:内存中的文件模拟在 内存中读写字符串或字节,无需真实文件,常用于测试、缓存、API 响应。
StringIO(文本)from io import StringIO
# 写入内存
f = StringIO()
f.write("Hello, ")
f.write("World!")
content = f.getvalue() # "Hello, World!"
f.close()
# 读取内存
f = StringIO("Line 1\nLine 2\nLine 3")
for line in f:
print(line.strip())
f.close()
# with 语句自动关闭
with StringIO() as f:
f.write("Test")
print(f.getvalue()) # Test
BytesIO(二进制)from io import BytesIO # 模拟二进制文件(如图片、PDF) buffer = BytesIO() buffer.write(b'\x89PNG\r\n\x1a\n') # PNG 文件头 png_data = buffer.getvalue() buffer.close()
✅ 典型用途:
- 单元测试中模拟文件对象
- 将数据直接传给需要 file-like object 的函数(如
pandas.read_csv(StringIO(...)))
pickle 模块:Python 对象序列化将 任意 Python 对象(包括自定义类)序列化为二进制,用于保存/恢复程序状态。
import pickle
data = {'users': ['Alice', 'Bob'], 'count': 42, 'flag': True}
# 序列化到文件
with open('data.pkl', 'wb') as f: # 注意:二进制模式 'wb'
pickle.dump(data, f)
# 从文件反序列化
with open('data.pkl', 'rb') as f: # 'rb'
loaded = pickle.load(f)
print(loaded) # {'users': ['Alice', 'Bob'], ...}
# 转为 bytes serialized = pickle.dumps(data) # 从 bytes 恢复 restored = pickle.loads(serialized)
⚠️ 严重警告:
- 不要反序列化不可信来源的 pickle 数据!(可执行任意代码)
- pickle 不是跨语言格式(仅限 Python)
- 不同 Python 版本可能不兼容
✅ 适用场景: 临时缓存、进程间通信(同一系统)、机器学习模型保存(如
joblib基于 pickle)
with 语句:上下文管理器(Context Manager)确保资源(如文件、锁、网络连接) 自动正确释放,即使发生异常。
# 自动关闭文件,无需 f.close()
with open('file.txt', 'r') as f:
content = f.read()
# 文件在此处已关闭
with open('input.txt', 'r') as fin, open('output.txt', 'w') as fout:
fout.write(fin.read().upper())
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"耗时: {time.time() - self.start:.2f}秒")
with Timer():
time.sleep(1) # 耗时: 1.00秒
✅ 核心优势:
- 避免资源泄漏(如忘记关闭文件)
- 代码更简洁、安全
- 自动处理异常后的清理
| 格式/模块 | 可读性 | 跨语言 | 安全性 | 适用场景 |
| ---------------- | ----------- | -------- | ------------------ | ----------------------- |
|
csv | ✅ 高 | ✅ 是 | ✅ 安全 | 表格数据交换 |
|
json | ✅ 高 | ✅ 是 | ✅ 安全 | Web API、配置文件 |
|
xml | ⚠️ 中 | ✅ 是 | ✅ 安全 | 企业级数据、文档 |
|
pickle | ❌ 二进制 | ❌ 否 | ❌
危险 | Python 内部对象持久化 |
|
StringIO | — | — | — | 内存中模拟文件 |
除非你百分百确定数据是你自己生成的,而且只在 Python 里用。不然 pickle 不光别人看不懂,还可能被用来搞坏事(比如执行恶意代码)。
with这样不管程序跑没跑完、出没出错,文件都会自动关掉。省得忘了关,占着资源还容易出 bug。
encoding='utf-8'特别是处理中文的时候,不加这个很容易乱码。加上就安心,一劳永逸。
DictReader 和
DictWriter用字典操作字段名(比如
row['name']),比记第几列直观多了,代码也更好读、好维护。
lxml标准库的 XML 功能比较基础。如果你要查节点、做转换或者验证结构,直接上
lxml,它支持 XPath,写起来爽很多。
pickle 本质是“把代码存下来再运行”,反序列化时可能偷偷执行东西,安全风险很高!
StringIO 模拟文件不用真在硬盘上建文件,直接在内存里读写,干净又快,测完就丢,特别适合单元测试。
公众号:咚咚王

《Python编程:从入门到实践》 《利用Python进行数据分析》 《算法导论中文第三版》 《概率论与数理统计(第四版) (盛骤) 》 《程序员的数学》 《线性代数应该这样学第3版》 《微积分和数学分析引论》 《(西瓜书)周志华-机器学习》 《TensorFlow机器学习实战指南》 《Sklearn与TensorFlow机器学习实用指南》 《模式识别(第四版)》 《深度学习 deep learning》伊恩·古德费洛著 花书 《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》 《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen) 》 《自然语言处理综论 第2版》 《Natural-Language-Processing-with-PyTorch》 《计算机视觉-算法与应用(中文版)》 《Learning OpenCV 4》 《AIGC:智能创作时代》杜雨+&+张孜铭 《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》 《从零构建大语言模型(中文版)》 《实战AI大模型》 《AI 3.0》
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048224/viewspace-3102497/ ,如需转载,请注明出处,否则将追究法律责任。