Python3 文件操作:从基础到高级的完整指南

Python 文件操作:读写文件这件事,记住 with open 就够了

写程序,文件操作避不开。读配置、写日志、处理数据、导出报表——天天都在跟文件打交道。

Python 的文件操作其实就一件事:with open() 打开文件,然后读或写。语法很简单,但实际用的时候有些细节——编码、大文件、异常处理——不注意就会出问题。

核心原则:永远用 with open

# 推荐写法
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
# 文件自动关闭,不用手动 close

# 不推荐
f = open("data.txt", "r")
content = f.read()
f.close()  # 万一前面报错,close 不会执行

with 语句会在代码块结束后自动关闭文件,即使中间抛异常也一样。记住这一点,就不用操心资源泄露的问题了。

读文件:三种方式,按需取用

1. 小文件:直接读完

with open("config.json", "r", encoding="utf-8") as f:
    content = f.read()

文件不大的时候,这是最直接的写法。几 MB 以内的文件都没问题。

2. 大文件:逐行读,不占内存

with open("large_log.txt", "r", encoding="utf-8") as f:
    for line in f:
        # 处理每一行
        if "ERROR" in line:
            print(line.strip())

for line in f 是逐行读取,不会一次性把所有内容加载到内存。处理几 GB 的日志文件就用这个方式。

3. 读所有行到列表

with open("data.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    # lines 是一个列表,每行一个元素

注意 readlines() 会把所有行都读进内存,适合小文件。大文件还是用上面的逐行遍历。

写文件:覆盖还是追加

# 覆盖写('w'):文件存在就清空,不存在就创建
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
    f.write("第二行\n")

# 追加写('a'):在文件末尾添加
with open("output.txt", "a", encoding="utf-8") as f:
    f.write("第三行\n")

写多行:

lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("output.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

writelines() 不会自动加换行,需要自己在字符串里带上 \n

编码:别偷懒,每次都指定 utf-8

# 指定编码
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()

# 不指定编码,在不同系统上可能出问题
with open("data.txt", "r") as f:
    content = f.read()

Windows 上默认编码可能是 gbk,Linux 上是 utf-8。 不指定编码的话,同样的代码在不同环境表现不一样。每次都写 encoding="utf-8" 是最省事的做法。

如果遇到 UnicodeDecodeError,说明文件编码不是 utf-8,换成其他编码试试:

try:
    with open("data.txt", "r", encoding="utf-8") as f:
        content = f.read()
except UnicodeDecodeError:
    with open("data.txt", "r", encoding="gbk") as f:
        content = f.read()

二进制文件:图片、音频、视频

读二进制文件用 'rb',写用 'wb',不需要指定编码。

# 读图片
with open("image.jpg", "rb") as f:
    data = f.read()
    print(f"文件大小:{len(data)} 字节")

# 复制文件
with open("source.jpg", "rb") as src:
    with open("copy.jpg", "wb") as dst:
        dst.write(src.read())

复制大文件不要一次性读完,应该分块读写:

chunk_size = 8192
with open("source.iso", "rb") as src:
    with open("copy.iso", "wb") as dst:
        while True:
            chunk = src.read(chunk_size)
            if not chunk:
                break
            dst.write(chunk)

文件存在性判断和目录操作

判断文件/目录是否存在:

from pathlib import Path

p = Path("data.txt")

if p.exists():
    if p.is_file():
        print("是文件")
    elif p.is_dir():
        print("是目录")

创建目录:

from pathlib import Path

# 创建单级目录
Path("data").mkdir(exist_ok=True)

# 创建多级目录
Path("data/2026/logs").mkdir(parents=True, exist_ok=True)

exist_ok=True 的意思是”目录存在也不报错”,省得每次都要先判断。

遍历目录:

from pathlib import Path

# 找所有 .txt 文件
for file in Path(".").glob("*.txt"):
    print(file)

# 递归遍历所有子目录
for file in Path(".").rglob("*.log"):
    print(file)

os 模块的老写法也常见:

import os

os.path.exists("data.txt")
os.path.isdir("data")
os.makedirs("data/logs", exist_ok=True)
os.listdir(".")

pathlib 是更新的写法,更直观;os 是老写法,老代码里常见。两种都认识就行,新代码推荐用 pathlib

CSV 文件:用 csv 模块,别自己 split

import csv

# 读 CSV
with open("data.csv", "r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    header = next(reader)  # 表头
    for row in reader:
        print(row)  # row 是列表

# 写 CSV
rows = [
    ["姓名", "年龄", "城市"],
    ["张三", 25, "北京"],
    ["李四", 30, "上海"],
]
with open("output.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

newline="" 是为了避免 Windows 上出现多余的空行,写 CSV 的时候加上就对了

JSON 文件:用 json 模块

import json

# 读 JSON
with open("config.json", "r", encoding="utf-8") as f:
    config = json.load(f)

# 写 JSON
data = {"name": "张三", "age": 25}
with open("output.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

ensure_ascii=False 保留中文,indent=2 让输出可读。这两个参数记不住的话,直接复制用就行。

异常处理:文件操作容易出错的地方

文件操作常见的异常就那么几种,处理好了程序就不会崩:

from pathlib import Path

file_path = Path("data.txt")

try:
    with open(file_path, "r", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print(f"文件不存在:{file_path}")
except PermissionError:
    print(f"没有读取权限:{file_path}")
except UnicodeDecodeError:
    print(f"编码错误:{file_path}")
except Exception as e:
    print(f"其他错误:{e}")

实际写代码的时候,至少把 FileNotFoundError 处理了,不然用户看到的就是一屏幕红字堆栈。

临时文件:用完自动删

import tempfile
from pathlib import Path

# 临时文件
with tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", delete=False) as f:
    f.write("临时数据")
    f.seek(0)
    print(f.read())

# 临时目录
with tempfile.TemporaryDirectory() as temp_dir:
    temp_file = Path(temp_dir) / "temp.txt"
    temp_file.write_text("临时文件")
    # 退出 with 块后自动删除

适合测试场景或者需要暂存中间数据的场景。