使用Python进行文件读写的API或方法及其注意事项

本文总结了Python文件读写的核心API及注意事项。


主要内容包括:

1)文件打开与关闭方法,推荐使用with语句自动管理资源;

2)文件读取方法,如read()、readline()等,注意大文件应使用迭代器方式;

3)文件写入方法及操作模式说明;

4)文件指针操作和常用辅助参数设置。


最佳实践建议:始终使用with语句,明确指定编码,根据场景选择合适方法(如大文件用迭代器)。


常见错误包括编码问题、文件指针位置错误等,可通过指定正确编码、seek(0)重置指针等方式解决。


使用Python进行文件读写的API或方法及其注意事项


以下是 Python 文件读写的核心 API 及注意事项总结表:


一、文件打开与关闭

API/方法 功能说明 示例 注意事项
open(file, mode, encoding) 打开文件,返回文件对象 f = open('test.txt', 'r', encoding='utf-8') 1. 必须指定正确的编码(如 utf-8) 2. 文件不存在时 'r' 模式会报错 FileNotFoundError 3. 建议使用 with 语句自动管理资源
close() 关闭文件对象 f.close() 1. 忘记关闭可能导致内存泄漏或数据丢失 2. 已关闭的文件无法再进行读写操作 3. 使用 with 语句可自动调用
with 语句 上下文管理器,自动关闭文件 with open('test.txt', 'r') as f: 推荐使用,即使发生异常也会自动关闭文件

二、文件读取方法

API/方法 功能说明 返回值 注意事项
read(size=-1) 读取指定字节数,默认读取全部 字符串 1. 大文件不建议无参读取,会耗尽内存 2. 读取后文件指针移动到末尾 3. 再次调用返回空字符串
readline(size=-1) 读取一行 字符串(包含换行符 \n 1. 文件末尾返回空字符串 '' 2. 换行符会被保留 3. 可用 strip() 去除换行符
readlines(hint=-1) 读取所有行 字符串列表(每行含 \n 1. 大文件同样有内存风险 2. 可用 for line in f: 逐行迭代更高效
迭代器方式 逐行读取(内存友好) 每行字符串 for line in f: process(line) *** ** * ** *** 推荐大文件使用,不会一次性加载全部内容

三、文件写入方法

API/方法 功能说明 示例 注意事项
write(str) 写入字符串 f.write('Hello\n') 1. 不会自动添加换行符,需手动加 \n 2. 返回写入的字符数 3. 需要配合 flush()close() 确保写入磁盘
writelines(lines) 写入字符串列表 f.writelines(['a\n', 'b\n']) 1. 不会自动添加换行符 2. 需要自己保证每个元素末尾有 \n 3. 适用于批量写入
flush() 强制刷新缓冲区 f.flush() 立即将缓冲区数据写入磁盘,避免数据丢失

四、文件操作模式

模式 说明 文件指针位置 文件不存在 原有内容
'r' 只读(默认) 文件开头 报错 FileNotFoundError 保留
'w' 只写(覆盖) 文件开头 创建新文件 清空
'a' 追加 文件末尾 创建新文件 保留
'x' 独占创建 文件开头 创建新文件 不存在(文件存在则报错)
'r+' 读写 文件开头 报错 保留(从头覆盖)
'w+' 读写(覆盖) 文件开头 创建新文件 清空
'a+' 读追加 文件末尾 创建新文件 保留
'b' 二进制模式 视主模式而定 视主模式而定 与文本模式配合使用,如 'rb', 'wb'

五、文件指针操作

API/方法 功能说明 示例 注意事项
tell() 返回当前指针位置(字节数) pos = f.tell() 1. 文本模式下可能不准确(多字节字符) 2. 二进制模式更可靠
seek(offset, whence) 移动文件指针 f.seek(0, 0) 移到开头 1. whence: 0=开头,1=当前位置,2=末尾 2. 文本模式只支持 whence=0 3. offset 需配合 tell() 返回值

六、常用辅助操作

API/方法 功能说明 示例 注意事项
encoding 参数 指定文件编码 encoding='utf-8' 1. 必须指定,避免平台依赖 2. 常用编码:utf-8, gbk, gb2312
errors 参数 处理编码错误 errors='ignore''replace' 1. 'ignore' 忽略错误 2. 'replace'? 替换 3. 'strict' 抛出异常(默认)
newline 参数 控制换行符处理 newline='' 1. 读写 CSV 时建议设为 '' 2. 避免跨平台换行符问题

七、最佳实践总结

场景 推荐方法 示例代码
读小文件(<100MB) read() data = f.read()
读大文件 迭代器 for line in f: process(line)
读配置文件 readlines() 或迭代 lines = f.readlines()
写少量数据 write() f.write('data')
写大量数据 writelines() f.writelines(lines)
需要随机访问 seek() + tell() 配合二进制模式使用
二进制文件(图片等) 'rb' / 'wb' f.read(1024) 分块读取
自动资源管理 with 语句 始终推荐

八、常见错误与解决方案

错误类型 典型错误信息 解决方案
编码错误 'gbk' codec can't decode... 指定正确的 encoding 参数
文件不存在 FileNotFoundError 检查路径或使用 'w'/'a' 模式
权限错误 PermissionError 关闭其他程序占用,检查文件只读属性
指针错误 读到空数据 检查是否在 read() 后忘了 seek(0)
换行符问题 写入内容挤在一行 手动添加 \n 或使用 print(file=f)

九、典型完整示例

python

复制代码
# 推荐的标准写法
with open('file.txt', 'r', encoding='utf-8') as f:
    for line in f:  # 逐行读取,内存友好
        print(line.strip())

# 写入示例
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('第一行\n')
    f.writelines(['第二行\n', '第三行\n'])
    # 无需手动 close()

这个表格涵盖了 Python 文件操作的主要 API 和使用要点,建议在实际开发中优先使用 with 语句并明确指定编码。


补充:文件操作模式


以下是 Python 文件操作模式的完整补充,包括所有组合模式及详细说明:

一、基础模式完整版

模式 读写权限 文件指针位置 文件不存在 原有内容处理 典型应用场景
'r' 只读 开头 报错 保留 读取配置文件、日志分析
'w' 只写 开头 创建 清空 生成新文件、覆盖旧数据
'a' 只写 末尾 创建 保留 日志记录、追加数据
'x' 只写 开头 创建(独占) 不存在 防止覆盖、创建锁文件
'r+' 读写 开头 报错 保留 修改文件特定位置
'w+' 读写 开头 创建 清空 需要读写的全新文件
'a+' 读写 末尾 创建 保留 追加并读取(如日志分析)

二、二进制模式组合

模式 说明 数据类型 换行符处理 典型应用
'rb' 二进制只读 bytes 无转换 图片、视频、PDF、压缩包
'wb' 二进制只写 bytes 无转换 保存图片、序列化数据
'ab' 二进制追加 bytes 无转换 合并二进制文件
'xb' 二进制独占创建 bytes 无转换 避免覆盖二进制文件
'rb+' 二进制读写 bytes 无转换 修改二进制文件特定字节
'wb+' 二进制读写(覆盖) bytes 无转换 创建可读写的二进制文件
'ab+' 二进制读写(追加) bytes 无转换 追加并读取二进制数据

三、特殊模式组合

模式 说明 行为特点 注意事项 示例场景
'rt' 文本只读(默认) 'r' 文本模式的标准写法 明确指定文本模式
'wt' 文本只写 'w' 明确指定文本模式 生成文本文件
'at' 文本追加 'a' 明确指定文本模式 日志追加
'U' 通用换行模式 已弃用 Python 3 中不再使用 历史代码兼容

四、模式详细行为对比

4.1 文件指针位置详解

python

复制代码
# 演示不同模式的指针位置
with open('test.txt', 'w') as f:
    f.write('1234567890')

# r+ 模式:指针在开头
with open('test.txt', 'r+') as f:
    print(f.tell())  # 0
    f.write('ABC')
    f.seek(0)
    print(f.read())  # ABC4567890

# a+ 模式:指针在末尾
with open('test.txt', 'a+') as f:
    print(f.tell())  # 10(文件末尾)
    f.write('XYZ')
    f.seek(0)
    print(f.read())  # ABC4567890XYZ

4.2 读写操作行为差异

模式 执行 read() 执行 write() 执行 seek() 缓冲区行为
'r' ✅ 可以 ❌ 报错 ✅ 可以 行缓冲
'w' ❌ 报错 ✅ 可以 ✅ 可以 行缓冲
'a' ❌ 报错 ✅ 可以(始终末尾) 可移动但写操作回到末尾 行缓冲
'r+' ✅ 可以 ✅ 可以(覆盖) ✅ 可以 行缓冲
'w+' ✅ 可以 ✅ 可以(清空后) ✅ 可以 行缓冲
'a+' ✅ 可以(需先 seek) ✅ 可以(始终末尾) 读可移动,写强制末尾 行缓冲

4.3 错误处理行为

python

复制代码
# 不同模式对错误的处理
import os

# 模式 'x' - 文件存在时报错
try:
    with open('existing.txt', 'x') as f:
        f.write('data')
except FileExistsError:
    print("文件已存在,无法创建")

# 模式 'r' - 文件不存在时报错
try:
    with open('not_exist.txt', 'r') as f:
        data = f.read()
except FileNotFoundError:
    print("文件不存在")

# 模式 'w' - 自动创建,不报错
with open('new_file.txt', 'w') as f:
    f.write('自动创建成功')

五、平台差异性说明

模式 Linux/macOS 行为 Windows 行为 注意事项
文本模式换行符 \n \r\n 自动转换 跨平台时注意编码
二进制模式 无转换 无转换 推荐处理非文本文件
'a' 模式 写操作始终末尾 写操作始终末尾 Windows 某些情况有差异
文件锁定 通常不锁定 可能部分锁定 Windows 更严格

六、实际应用场景示例

6.1 配置文件读写

python

复制代码
# 使用 'r' 读取配置
def read_config():
    with open('config.txt', 'r', encoding='utf-8') as f:
        return dict(line.strip().split('=') for line in f)

# 使用 'w' 保存配置
def save_config(config):
    with open('config.txt', 'w', encoding='utf-8') as f:
        for key, value in config.items():
            f.write(f"{key}={value}\n")

6.2 日志文件追加

python

复制代码
import datetime

def log_message(msg):
    # 'a' 模式自动追加,不会覆盖历史日志
    with open('app.log', 'a', encoding='utf-8') as f:
        timestamp = datetime.datetime.now()
        f.write(f"[{timestamp}] {msg}\n")

6.3 二进制文件处理

python

复制代码
# 复制图片(二进制模式)
def copy_image(src, dst):
    with open(src, 'rb') as source:
        with open(dst, 'wb') as target:
            # 分块复制,避免内存爆炸
            while chunk := source.read(8192):
                target.write(chunk)

# 修改二进制文件特定位置
def patch_binary(filepath, offset, new_bytes):
    with open(filepath, 'r+b') as f:
        f.seek(offset)
        f.write(new_bytes)

6.4 临时文件安全创建

python

复制代码
# 使用 'x' 模式避免覆盖
def safe_save(data, filename):
    try:
        with open(filename, 'x', encoding='utf-8') as f:
            f.write(data)
        print(f"成功创建 {filename}")
    except FileExistsError:
        print(f"文件 {filename} 已存在,拒绝覆盖")
        # 可以生成新文件名
        base, ext = os.path.splitext(filename)
        new_name = f"{base}_new{ext}"
        return safe_save(data, new_name)

6.5 文件内容原地修改

python

复制代码
# 使用 'r+' 模式修改文件特定行
def replace_line(filename, line_num, new_content):
    with open(filename, 'r+', encoding='utf-8') as f:
        lines = f.readlines()
        if 0 <= line_num < len(lines):
            lines[line_num] = new_content + '\n'
            f.seek(0)
            f.writelines(lines)
            f.truncate()  # 截断多余内容

6.6 CSV 文件处理

python

复制代码
import csv

# 读取 CSV(文本模式)
def read_csv(filename):
    with open(filename, 'r', newline='', encoding='utf-8') as f:
        return list(csv.reader(f))

# 写入 CSV(文本模式)
def write_csv(filename, data):
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerows(data)

七、高级模式与标志位(底层 os.open)

os 标志 说明 Python 等效 用途
os.O_RDONLY 只读 'r' 底层文件操作
os.O_WRONLY 只写 'w' 底层文件操作
os.O_RDWR 读写 'r+' 底层文件操作
os.O_CREAT 不存在则创建 'w', 'a' 自动创建
os.O_EXCL O_CREAT 配合独占创建 'x' 原子性创建
os.O_TRUNC 截断文件 'w' 清空内容
os.O_APPEND 追加模式 'a' 原子性追加
os.O_SYNC 同步写入 无直接等效 性能与可靠性平衡

八、性能对比与选择建议

场景 推荐模式 性能特点 理由
大文件只读 'r' 利用系统缓存
频繁小写入 'a' 避免重复 seek
随机读写 'r+b' 需要多次 seek
日志追加 'a' 原子性操作
临时文件 'x' 避免冲突
二进制拷贝 'rb', 'wb' 无编码转换开销

九、常见陷阱与解决方案

陷阱 表现 解决方案
忘记二进制模式 图片读写乱码 使用 'rb'/'wb'
'a+' 读不到数据 read() 返回空 seek(0) 再读
'r+' 意外覆盖 写入位置不对 精确使用 seek()
'w' 清空数据 原有数据丢失 改用 'a' 或备份
换行符混乱 Windows 下 \r\n 问题 二进制模式或指定 newline

十、完整决策树

python

复制代码
# 选择文件模式的决策逻辑
def choose_mode(read_needed, write_needed, append_mode, binary_mode, safe_create):
    if binary_mode:
        mode_base = 'b'
    else:
        mode_base = 't'  # 可省略
    
    if read_needed and write_needed:
        if safe_create:
            return 'w+' + mode_base  # 安全创建但会清空
        elif append_mode:
            return 'a+' + mode_base
        else:
            return 'r+' + mode_base
    elif read_needed:
        return 'r' + mode_base
    elif write_needed:
        if safe_create:
            return 'x' + mode_base
        elif append_mode:
            return 'a' + mode_base
        else:
            return 'w' + mode_base
    else:
        raise ValueError("至少需要读或写权限")

# 使用示例
print(choose_mode(True, False, False, False, False))  # 'r'
print(choose_mode(True, True, True, False, False))    # 'a+'
print(choose_mode(False, True, False, True, False))   # 'wb'
print(choose_mode(False, True, False, False, True))   # 'x'

这个补充涵盖了 Python 文件操作模式的所有细节,建议根据具体场景选择合适的模式组合。


错误示例:错误分析


python 复制代码
#读文件
with open("C:\\Users\\86178\\Desktop\\aaa.txt",'r',encoding="utf-8") as f:
    con=f.read()#将文本的内容作为一个整体字符串,读出来
    con1=f.readline()
    con2 = f.readlines()#把文本每行的内容 作为一个元素 放到列表里面
    print(con)
    #输出
    # aaa
    # bbb
    # ccc
    print(con1)#换行?
    print(con2)#[]?
    f.close()#关闭该线程 关闭文件

你的代码存在一个关键问题 :在调用了 f.read() 之后,文件指针已经移动到了文件末尾,因此后续的 f.readline()f.readlines() 无法再读取到任何内容。


问题分析

  1. f.read() 读取整个文件,指针移到最后

  2. f.readline() 从当前位置(文件末尾)读取,返回空字符串 ''

  3. f.readlines() 同样从末尾读取,返回空列表 []

  4. 你看到的 print(con1) 输出空行,是因为打印了空字符串后自动换行

  5. f.close() 其实可以省略(with 语句会自动关闭)


修正后的代码

方案一:只使用一种读取方式

python

复制代码
with open("C:\\Users\\86178\\Desktop\\aaa.txt", 'r', encoding="utf-8") as f:
    con = f.read()  # 整体读取
    print(con)

方案二:分别读取(需要重新打开或重置指针)

python

复制代码
with open("C:\\Users\\86178\\Desktop\\aaa.txt", 'r', encoding="utf-8") as f:
    con = f.read()
    print("read()结果:")
    print(con)
    
    # 将指针移回文件开头
    f.seek(0)
    
    con1 = f.readline()
    print("readline()结果:", repr(con1))  # 使用repr可以看到转义字符
    
    con2 = f.readlines()
    print("readlines()结果:", con2)

方案三:分别打开文件

python

复制代码
# 分别演示三种读取方式
with open("C:\\Users\\86178\\Desktop\\aaa.txt", 'r', encoding="utf-8") as f:
    print("1. read():")
    print(f.read())

with open("C:\\Users\\86178\\Desktop\\aaa.txt", 'r', encoding="utf-8") as f:
    print("\n2. readline():")
    print(repr(f.readline()))

with open("C:\\Users\\86178\\Desktop\\aaa.txt", 'r', encoding="utf-8") as f:
    print("\n3. readlines():")
    print(f.readlines())

补充说明

  • readline() :返回一行字符串(包含换行符 \n),文件末尾返回空字符串 ''

  • readlines():返回所有行的列表,每行字符串包含换行符

  • repr() 函数可以显示字符串的真实内容,包括 \n 等转义字符

  • seek(0) :将文件指针移动到指定位置,0 表示文件开头


类似错误


python 复制代码
with open('day_07.py','w+',encoding="utf-8") as f:
    f.writelines("hello world\n")#覆盖写入
    con = f.read()
    print(con)#为什么读不出数据?
    f.close()

问题在于文件指针位置!你的代码流程如下:


问题分析

python

复制代码
with open('day_07.py', 'w+', encoding="utf-8") as f:
    f.writelines("hello world\n")  # 1. 写入数据,指针在末尾(第13个字节后)
    con = f.read()                  # 2. 从末尾读取 → 读不到任何数据
    print(con)                      # 3. 输出空字符串
    f.close()                       # 4. with 语句会自动关闭,此行多余

关键点

  • writelines() 写入后,文件指针停留在写入内容的末尾

  • 此时调用 read(),从末尾开始读 → 返回空字符串


解决方案

方案一:先 seek(0) 再读取

python

复制代码
with open('day_07.py', 'w+', encoding="utf-8") as f:
    f.writelines("hello world\n")
    f.seek(0)  # 将指针移回文件开头
    con = f.read()
    print(con)  # 输出: hello world

方案二:先写入,关闭后重新读取

python

复制代码
# 先写入
with open('day_07.py', 'w', encoding="utf-8") as f:
    f.writelines("hello world\n")

# 再读取
with open('day_07.py', 'r', encoding="utf-8") as f:
    con = f.read()
    print(con)  # 输出: hello world

方案三:使用 r+ 模式(需要文件已存在)

python

复制代码
# 先创建文件
with open('day_07.py', 'w', encoding="utf-8") as f:
    f.writelines("hello world\n")

# 再读写
with open('day_07.py', 'r+', encoding="utf-8") as f:
    con = f.read()
    print(con)  # 输出: hello world
    f.write("\n追加内容")  # 在末尾追加

各模式写入后的指针位置

模式 写入操作 写入后指针位置 立即读取结果
'w+' write() / writelines() 文件末尾 空字符串(需 seek(0)
'r+' write() 写入位置末尾(可能覆盖) 取决于写入位置
'a+' write() 始终在文件末尾 空字符串(需 seek(0)
'w' write() 文件末尾 不支持读取

验证指针位置

python

复制代码
# 演示指针位置变化
with open('day_07.py', 'w+', encoding="utf-8") as f:
    print(f"初始位置: {f.tell()}")  # 0
    
    f.writelines("hello world\n")
    print(f"写入后位置: {f.tell()}")  # 13(假设12个字符+换行符)
    
    f.seek(0)
    print(f"seek(0)后位置: {f.tell()}")  # 0
    
    con = f.read()
    print(f"读取后位置: {f.tell()}")  # 13(读完又到末尾)
    print(f"读取内容: {con}")  # hello world

正确的 w+ 使用场景

w+ 模式适合以下场景:

场景1:写入后立即读取(需 seek)

python

复制代码
with open('temp.txt', 'w+', encoding="utf-8") as f:
    # 生成数据
    for i in range(10):
        f.write(f"第{i}行\n")
    
    # 需要读取时,先回到开头
    f.seek(0)
    data = f.read()
    print(data)

场景2:清空文件后重新写入并验证

python

复制代码
with open('config.txt', 'w+', encoding="utf-8") as f:
    f.write("new config data")
    f.seek(0)
    
    # 验证写入是否正确
    if f.read() == "new config data":
        print("写入成功")

场景3:在内存中处理数据

python

复制代码
# 使用 StringIO 更好,但 w+ 也可以
with open('data.txt', 'w+', encoding="utf-8") as f:
    # 先生成内容
    lines = ["line1\n", "line2\n", "line3\n"]
    f.writelines(lines)
    
    # 处理这些数据
    f.seek(0)
    processed = [line.upper() for line in f]
    print(processed)  # ['LINE1\n', 'LINE2\n', 'LINE3\n']

其他注意事项

1. close() 是多余的

python

复制代码
# with 语句会自动关闭文件,不需要手动 close()
with open('day_07.py', 'w+', encoding="utf-8") as f:
    f.write("data")
    f.seek(0)
    print(f.read())
# 离开 with 块时自动关闭

2. writelines() 不会自动换行

python

复制代码
# writelines() 不会自动添加换行符
with open('test.txt', 'w+') as f:
    f.writelines(["hello", "world"])  # 结果是 "helloworld"
    
# 需要手动添加
with open('test.txt', 'w+') as f:
    f.writelines(["hello\n", "world\n"])  # 正确

3. 更清晰的替代方案

python

复制代码
# 如果只是创建新文件并写入,用 'w' 模式
with open('day_07.py', 'w', encoding="utf-8") as f:
    f.writelines("hello world\n")

# 单独读取
with open('day_07.py', 'r', encoding="utf-8") as f:
    print(f.read())

总结

你的代码读不出数据的原因writelines() 后指针在文件末尾,read() 从末尾开始读导致返回空字符串。

解决方法 :在读取前添加 f.seek(0) 将指针移回开头。

最佳实践 :除非确实需要读写切换,否则建议使用单一目的的模式'r' 只读或 'w' 只写),代码意图更清晰。

相关推荐
weixin_424999362 小时前
mysql如何防止索引被错误使用_mysql查询计划强制约束
jvm·数据库·python
旦莫2 小时前
测试工程师如何用AI生成测试用例?我的提示词模板分享
人工智能·python·测试开发·自动化·测试用例·ai测试
itzixiao2 小时前
L1-047 装睡 (5分)[java][python]
java·开发语言·python
m0_613856292 小时前
Golang怎么实现测试跳过条件_Golang如何根据环境或条件跳过不适用的测试用例【操作】
jvm·数据库·python
unicrom_深圳市由你创科技2 小时前
上位机开发常用的语言 / 框架有哪些?
c++·python·c#
abc123456sdggfd2 小时前
bootstrap如何修改输入框获取焦点时的光晕
jvm·数据库·python
qq_330037993 小时前
如何配置ASM元数据备份_md_backup与md_restore重建磁盘组结构
jvm·数据库·python
昭昭日月明3 小时前
前端仔速通 Python
javascript·python
a9511416423 小时前
SQL触发器实现自动生成流水号_配合序列对象实现递增逻辑
jvm·数据库·python