Python 文件操作
真正有用的程序几乎都要和文件打交道——读配置、写日志、处理数据、保存结果。Python 的文件操作极其简洁,这一章把读写、路径处理、CSV/JSON、目录操作全讲透。
1. 打开文件:open
# open(文件名, 模式) 打开文件,返回文件对象
# 模式:r 读(默认)、w 写(覆盖)、a 追加、b 二进制、+ 读写
# 1. 写文件(w 模式:文件不存在则创建,存在则覆盖)
f = open("hello.txt", "w", encoding="utf-8")
f.write("第一行\n")
f.write("第二行\n")
f.close() # ⚠ 必须手动关闭!不关会泄漏资源
# 2. 读文件(r 模式)
f = open("hello.txt", "r", encoding="utf-8")
content = f.read() # 一次性读完
print(content)
f.close()
# 输出:
# 第一行
# 第二行务必加 encoding="utf-8":Windows 默认编码是 GBK,不加这行读中文文件会乱码或报 UnicodeDecodeError。这是新手最常踩的坑。
2. with 语句:自动关闭(标准写法)
# with 语句:自动关闭文件,即使中间出错也不会忘记
# 这是 Python 文件操作的标准写法
# 写文件
with open("note.txt", "w", encoding="utf-8") as f:
f.write("学习 Python\n")
f.write("文件操作很重要\n")
# with 块结束,文件自动关闭
# 读文件
with open("note.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
# 强烈推荐:任何文件操作都用 with,不要用 open + close
# 这避免了"忘记 close"或"中间抛异常导致文件未关"的资源泄漏问题这是 Python 文件操作的事实标准,任何文件操作都该用 with,不要手动 open/close。原因:
- with 块结束自动调用
f.close()。 - 即使中间抛异常,with 也会保证关闭。
- 不用记着写 close,代码更清爽。
3. 读取文件的几种方式
# 多种读取方式
# 1. read():一次性读取整个文件(小文件用)
with open("note.txt", "r", encoding="utf-8") as f:
print(f.read())
# 2. readline():每次读一行
with open("note.txt", "r", encoding="utf-8") as f:
line1 = f.readline()
line2 = f.readline()
print(line1, line2)
# 3. readlines():读取所有行,返回列表(每行一个元素)
with open("note.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print(lines) # ['学习 Python\n', '文件操作很重要\n']
# 4. ⭐ 最佳实践:直接 for 循环逐行读(内存友好,大文件用)
with open("note.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip()) # strip() 去掉末尾换行符读大文件首选 for 循环逐行读(第 4 种方式)。f.read() 会把整个文件加载进内存,处理几 GB 的大文件会爆内存;逐行读只占一行内存。
4. 写文件:w 与 a 模式
# 写文件的几种方式
# w 模式:覆盖(原文件被清空!)
with open("log.txt", "w", encoding="utf-8") as f:
f.write("覆盖写\n")
# a 模式:追加(在文件末尾添加)
with open("log.txt", "a", encoding="utf-8") as f:
f.write("追加一行\n")
f.write("再追加一行\n")
# writelines():写入一个列表(每个元素一行,但不会自动加换行符)
lines = ["苹果\n", "香蕉\n", "橘子\n"]
with open("fruits.txt", "w", encoding="utf-8") as f:
f.writelines(lines)
# print() 也能写文件(用 file 参数)
with open("greeting.txt", "w", encoding="utf-8") as f:
print("Hello", file=f)
print("World", file=f)w(覆盖)和 a(追加)的区别要记牢:用错模式会清空重要文件。建议不确定时用 x 模式(文件已存在会报错,防覆盖)。
5. 文件打开模式速查
# 文件打开模式速查
# r 读(默认)。文件不存在会报错 FileNotFoundError
# w 写。文件不存在则创建,存在则清空
# a 追加。文件不存在则创建,存在则末尾追加
# x 独占创建。文件已存在则报错(防止覆盖)
# b 二进制模式(配合上面用:rb/wb/ab)。处理图片/视频/压缩包
# t 文本模式(默认,通常不写)
# + 更新模式(可读可写:r+/w+/a+)
# 二进制读写(图片、视频、压缩包等)
with open("photo.jpg", "rb") as f: # rb 读二进制
data = f.read()
with open("copy.jpg", "wb") as f: # wb 写二进制
f.write(data)6. pathlib:现代路径处理(推荐)
pathlib 是 Python 3.4+ 的现代路径库,比传统的 os.path 优雅得多——能用 / 拼接路径,方法更直观。
# pathlib:现代路径处理(推荐,比 os.path 优雅)
from pathlib import Path
# 当前目录
p = Path(".")
print(p.absolute()) # 当前目录的绝对路径
# 创建路径对象(用 / 拼接,Python 重载了运算符!)
file_path = Path("data") / "users" / "users.json"
print(file_path) # data/users/users.json
# 常用操作
p = Path("data/users/users.json")
print(p.name) # users.json 文件名(含扩展名)
print(p.stem) # users 文件名(不含扩展名)
print(p.suffix) # .json 扩展名
print(p.parent) # data/users 父目录
print(p.exists()) # False/True 是否存在
print(p.is_file()) # 是否是文件
print(p.is_dir()) # 是否是目录
# 创建目录
Path("test_dir").mkdir(exist_ok=True) # 已存在不报错
# 列出目录下的所有文件
for child in Path(".").iterdir():
print(child)
# 用 glob 模式查找
for py_file in Path(".").glob("*.py"):
print(py_file)7. CSV 文件读写
CSV 是数据交换最常用的格式,Python 自带 csv 模块。
# CSV 文件处理(自带 csv 模块)
import csv
# 写 CSV
users = [
["姓名", "年龄", "城市"],
["小明", 20, "北京"],
["小红", 22, "上海"],
["小刚", 25, "广州"],
]
with open("users.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f)
writer.writerows(users) # 写多行
# 注意:
# - utf-8-sig:让 Excel 正确识别 UTF-8(中文不乱码)
# - newline="":避免 Windows 上多出空行
# 读 CSV
with open("users.csv", "r", encoding="utf-8-sig") as f:
reader = csv.reader(f)
for row in reader:
print(row)
# 输出:
# ['姓名', '年龄', '城市']
# ['小明', '20', '北京']
# ...
# DictReader:把每行读成字典(用表头作 key)
with open("users.csv", "r", encoding="utf-8-sig") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["姓名"], row["年龄"])几个坑点:utf-8-sig 让 Excel 正确识别中文(否则乱码);newline="" 避免 Windows 上多出空行。
8. JSON 文件读写
import json
# 写 JSON 文件
user = {"name": "小明", "age": 20, "hobbies": ["读书", "编程"]}
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user, f, ensure_ascii=False, indent=2)
# 读 JSON 文件
with open("user.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data["name"]) # 小明
print(data["hobbies"][0]) # 读书配置文件、API 数据持久化、缓存,JSON 是首选格式。ensure_ascii=False 让中文正常显示。
9. os 模块:目录与文件操作
# os 模块:文件和目录操作
import os
# 当前工作目录
print(os.getcwd()) # /Users/yourname/project
# 改变工作目录
# os.chdir("/tmp")
# 列出目录内容
print(os.listdir(".")) # ['hello.txt', 'note.txt', ...]
# 创建/删除目录
os.makedirs("a/b/c", exist_ok=True) # 递归创建
# os.rmdir("a/b/c") # 删空目录
# os.removedirs("a/b/c") # 递归删空目录
# 文件重命名/移动
# os.rename("old.txt", "new.txt")
# 删除文件
# os.remove("hello.txt")
# 路径相关(老式写法,推荐用 pathlib 替代)
print(os.path.join("a", "b", "c.txt")) # a/b/c.txt
print(os.path.exists("hello.txt")) # True
print(os.path.isfile("hello.txt")) # True
print(os.path.isdir(".")) # True
print(os.path.basename("/a/b/c.txt")) # c.txt
print(os.path.dirname("/a/b/c.txt")) # /a/b10. 编码问题排查
遇到 UnicodeDecodeError 或乱码,99% 是编码不一致。排查思路:
- 用编辑器(VS Code)打开文件,看右下角编码(UTF-8 / GBK / GB2312?)。
- 读取时显式指定对应编码:
open(..., encoding="gbk")。 - 写文件统一用 UTF-8,这是跨平台兼容的最佳选择。
小结
文件操作是真实程序的基础。重点掌握:open、with 语句(标准写法)、逐行读大文件、w/a 模式区别、pathlib 路径处理、CSV/JSON 读写、encoding="utf-8"。下一篇看异常处理——让程序健壮地处理意外。
← 上一篇 Python 类与面向对象
下一篇 Python 异常处理 →