Python

Python 文件操作完整详解

·15 分钟阅读·5852 字
📋 目录

Python 文件操作完整详解

核心概念 Python 文件操作核心基于内置 open() 函数,支持文本和二进制模式,配合 with 语句实现自动资源管理。

1. 文件操作核心基础

1.1. 核心内置函数 open()

Python 内置函数,用于打开文件,返回文件对象(file object),所有读写操作依托该对象完成。

1.1.1. 基础语法

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)

核心参数说明:

  1. file:文件路径(相对路径/绝对路径)
  2. mode:打开模式(读/写/追加/二进制),默认 r 只读文本
  3. encoding:文本文件编码(utf-8/gbk,二进制模式无需传)
  4. errors:编码错误处理策略(strict抛异常、ignore忽略、replace替换乱码)
  5. newline:控制换行符转换(Windows \r\n / Linux \n

1.2. 推荐写法:with 上下文管理器(必用)

原生 open() 不手动 close() 会导致文件句柄泄露,with 语句自动关闭文件,异常也会自动释放资源,生产标准写法:

# 自动close,无需手动调用f.close()
with open("test.txt", "r", encoding="utf-8") as f:
    data = f.read()
print(data)
# 代码块结束,文件自动关闭

2. 文件打开模式 mode 全分类

分为文本模式(t,默认)二进制模式(b) 两大类,不能混用。

2.1. 文本模式(处理txt、md、csv等文字,自动编码转换)

模式含义文件不存在文件存在指针位置
rread 只读(默认)抛 FileNotFoundError正常读取文件开头
wwrite 覆盖写自动创建清空全部内容再写入文件开头
aappend 追加写自动创建保留原有内容,新增内容放末尾文件末尾
r+读写报错可读可覆盖写入文件开头
w+清空读写创建清空原有内容文件开头
a+追加读写创建可读,写入只能在末尾文件末尾

2.2. 二进制模式(b,图片、视频、exe、压缩包、字节流,无编码)

在上面基础加 brb / wb / ab / rb+

  • 读写返回 bytes 字节对象,不能传 encoding 参数
  • 不会自动转换换行符,原样读写二进制数据
    示例:读取图片
with open("img.jpg", "rb") as f:
    img_bytes = f.read()

2.3. 补充关键区分

  1. r+:不会清空原文件,可修改中间内容;w+ 打开瞬间清空整个文件;
  2. a/a+ 无论怎么移动文件指针,write 写入永远追加到末尾;
  3. 文本模式不加 t,默认就是 rt;二进制必须显式写 b

3. 文件对象核心读写方法

3.1. (一)读取文件 3 种方法

3.1.1. read(size=-1):一次性读取全部内容

  • size:指定读取字节/字符数,默认-1读取全部
  • 文本模式返回字符串,二进制返回bytes
with open("test.txt", "r", encoding="utf-8") as f:
    content = f.read()          # 读取全部
    part = f.read(100)          # 读取前100个字符

缺点:超大文件一次性读入内存,易内存溢出。

3.1.2. readline():逐行读取,一次一行

末尾自带换行符 \n,无内容返回空字符串 ""

with open("test.txt", "r", encoding="utf-8") as f:
    line1 = f.readline()
    line2 = f.readline()

3.1.3. readlines():读取所有行,返回列表

每行作为列表元素,包含换行符,大文件不推荐

lines = f.readlines()
for line in lines:
    print(line.strip())

3.1.4. 迭代器遍历(推荐,内存最优)

文件对象本身是可迭代对象,逐行加载,不一次性加载全文件:

with open("test.txt", "r", encoding="utf-8") as f:
    for line in f:
        real_line = line.strip()  # 去除首尾换行空格
        print(real_line)

3.2. (二)写入文件 2 种方法

3.2.1. write(str / bytes)

文本模式传入字符串,二进制传入bytes;不会自动添加换行符,需手动加 \n

with open("write.txt", "w", encoding="utf-8") as f:
    f.write("第一行内容\n")
    f.write("第二行内容\n")

返回值:写入的字符/字节数量。

3.2.2. writelines(可迭代对象)

接收列表、元组等序列,批量写入多行;同样不会自动换行

lines = ["苹果\n", "香蕉\n", "橙子\n"]
f.writelines(lines)

3.3. (三)文件指针控制(seek / tell)

文件内部有读写指针,标记当前读写位置。

  1. f.tell():返回当前指针位置(字节偏移)
  2. f.seek(offset, whence):移动指针
  • offset:偏移量(正数向后,二进制模式支持负数)

  • whence 参考位置:

  • 0:文件开头(默认,文本模式仅支持0)

  • 1:当前位置(仅二进制可用)

  • 2:文件末尾(仅二进制可用)

示例:文本文件回到开头重新读取

with open("test.txt", "r", encoding="utf-8") as f:
    print(f.read())
    f.seek(0)  # 指针移到文件头部
    print(f.read())

示例:二进制读取最后100字节

with open("data.bin", "rb") as f:
    f.seek(-100, 2)
    last_data = f.read()

3.4. (四)其他常用方法

  • f.flush():强制把缓冲区内容刷入磁盘,不等待自动缓冲
  • f.close():手动关闭文件(with 无需调用)
  • f.closed:布尔值,判断文件是否已关闭
  • f.name:获取打开的文件路径

4. 缓冲区 buffering 机制

文件读写不会直接操作磁盘,先存入内存缓冲区,满足条件才刷盘:

  1. buffering=-1 默认:文本行缓冲,二进制4096字节块缓冲
  2. buffering=0:二进制无缓冲,实时写入磁盘;文本模式不允许0
  3. buffering=1:文本行缓冲,遇到换行自动刷盘
  4. buffering=N:缓冲区达到N字节自动刷盘

手动强制落盘:f.flush()

5. os / pathlib 路径与文件系统操作(配套必备)

单纯 open 只负责读写,文件创建、删除、判断存在、遍历目录需要 os 或新标准库 pathlib

5.1. pathlib(Python3.4+ 推荐,面向对象)

from pathlib import Path

# 1. 创建路径对象
p = Path("./test.txt")

# 判断
print(p.exists())       # 文件/目录是否存在
print(p.is_file())      # 是否是文件
print(p.is_dir())       # 是否是文件夹

# 创建/删除文件
p.touch()               # 创建空文件
p.unlink()              # 删除文件

# 目录操作
dir_p = Path("./data")
dir_p.mkdir(exist_ok=True) # 创建文件夹,存在不报错
dir_p.rmdir()           # 删除空文件夹

# 遍历目录
for file in Path("./").iterdir():
    print(file)

# 路径拼接
new_path = Path("./data") / "demo.txt"

5.2. os 模块(传统兼容写法)

import os

# 判断文件是否存在
os.path.exists("test.txt")
os.path.isfile("test.txt")
os.path.isdir("./dir")

# 创建/删除
os.makedirs("./data", exist_ok=True)
os.remove("test.txt")       # 删除文件
os.rmdir("./data")          # 删除空目录

# 遍历目录
os.listdir("./")

# 路径拼接(自动适配Windows/Linux分隔符)
file_path = os.path.join("./data", "1.txt")

6. 常见编码问题

  1. Windows 记事本默认编码 gbk,Linux/Mac 默认 utf-8,不指定encoding极易乱码;
  2. 报错 UnicodeDecodeError 解决方案:
  • 明确指定正确编码 encoding="gbk" / encoding="utf-8"
  • 容错读取:errors="replace" 乱码替换为�符号
# 兼容乱码文件
with open("gbk_file.txt", "r", encoding="gbk", errors="replace") as f:
    pass
  1. 二进制模式无需编码参数,读写原始字节。

7. 超大文件高效读取方案

禁止一次性 read() 全量加载,两种方案:

  1. 迭代器逐行读取(文本日志首选)
with open("big_log.txt", "r", encoding="utf-8") as f:
    for line in f:
        process(line)
  1. 固定分块读取(二进制大文件、压缩包)
CHUNK_SIZE = 4096
with open("large.bin", "rb") as f_in, open("copy.bin", "wb") as f_out:
    while chunk := f_in.read(CHUNK_SIZE):
        f_out.write(chunk)

8. 高频坑点与避坑

8.1. 忘记关闭文件,句柄泄露

错误写法:

# 异常时无法close,长期运行打开文件数超限报错
f = open("1.txt", "r")
data = f.read()
# 忘记 f.close()

✅ 统一使用 with 上下文管理器。

8.2. w 模式误删原有数据

打开 w/w+ 瞬间清空文件,重要文件优先用 r+a

8.3. 二进制/文本模式混用

图片、视频用 rb/wb,不能加 encoding;txt 文本不用 b 模式,否则读到bytes。

8.4. 相对路径歧义

程序运行目录不等于脚本所在目录,推荐使用绝对路径,或 __file__ 获取脚本真实路径:

from pathlib import Path
base = Path(__file__).parent  # 当前脚本所在文件夹
file_path = base / "test.txt"

8.5. 多行写入忘记手动加 \n

write / writelines 不会自动换行,不添加换行所有内容挤在同一行。

8.6. a+ 模式指针陷阱

即使 seek(0) 移到开头,调用 write() 依然追加到文件末尾,无法中间插入内容。

9. 完整实战示例

9.1. 示例1:文本文件读写(with标准模板)

# 写入
with open("note.txt", "w", encoding="utf-8") as f:
    f.write("Python 文件操作\n")
    f.writelines(["第一行\n", "第二行\n"])

# 读取
with open("note.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

9.2. 示例2:二进制文件复制(图片/视频)

CHUNK = 8192
with open("source.jpg", "rb") as src, open("target.jpg", "wb") as dst:
    while buf := src.read(CHUNK):
        dst.write(buf)

9.3. 示例3:r+ 模式修改文件中间内容

注意:只能覆盖字节,无法插入文字(插入需要整体重写文件)

with open("demo.txt", "r+", encoding="utf-8") as f:
    content = f.read()
    f.seek(0)
    f.write("【修改开头】\n" + content)

10. 面试核心速记总结

  1. 打开文件优先 with open() 上下文管理器,自动释放句柄,杜绝泄露;
  2. 模式区分文本(r/w/a/r+)、二进制(rb/wb/ab),二进制无encoding;
  3. w 清空文件,a 末尾追加,r+ 可读可写不清空;
  4. 读取:read()全量、readline()单行、迭代器逐行(大文件最优);
  5. seek()移动文件指针,tell()查看当前偏移;
  6. 超大文件分块/逐行读取,禁止一次性read占用内存;
  7. 路径操作新标准 pathlib,传统 os.path 兼容老项目;
  8. 中文乱码根源:未指定encoding,Windows文件多为gbk,Linux为utf-8;
  9. 二进制模式支持seek负数偏移,文本模式仅支持从文件头偏移;
  10. write/writelines不会自动换行,需要手动拼接\n

关联文档