欢迎光临
我们一直在努力

9. Python 文件与输入输出 深度解析

Python 文件与输入输出 深度解析

目录

  • Python I/O 概述
  • 文件对象与基本操作
    • 2.1 打开文件:open 与模式
    • 2.2 读取数据
    • 2.3 写入数据
    • 2.4 使用 with 自动管理文件
  • 文件指针与随机访问
  • 路径操作:os、os.path 与 pathlib
    • 4.1 os 模块与 os.path 基础
    • 4.2 现代路径处理:pathlib.Path
  • 二进制模式与内存视图
  • 序列化:json、pickle 与 csv
    • 6.1 JSON:通用数据交换格式
    • 6.2 Pickle:Python 原生序列化
    • 6.3 CSV:逗号分隔值处理
  • 内存中的虚拟文件:StringIO 与 BytesIO
  • 编码与解码深度解析
  • 高级文件处理
    • 9.1 目录遍历:os.walk 与 pathlib.rglob
    • 9.2 文件系统操作:拷贝、移动、删除
    • 9.3 临时文件与目录:tempfile
  • 常见陷阱与最佳实践
  • 总结

  • 1. Python I/O 概述

    输入/输出(I/O)是程序与外部世界交互的基础。Python 提供了一套灵活且强大的 I/O 设施,包括:

    • 文件读写(文本与二进制)
    • 内存中的流对象(StringIO、BytesIO)
    • 多种序列化格式(JSON、Pickle、CSV)
    • 目录与文件系统操作(os、pathlib)
    • 网络与管道等更高级的 I/O 接口

    本章将深入探讨 Python 文件与输入输出相关的核心概念与最佳实践,并配合大量示例。


    2. 文件对象与基本操作

    2.1 打开文件:open 与模式

    内置函数 open(file, mode='r', encoding=None) 返回一个文件对象,mode 决定操作类型:

    字符含义
    'r' 读取(默认)
    'w' 写入(覆盖),文件不存在则创建
    'x' 排它性创建,文件已存在则失败
    'a' 追加
    'b' 二进制模式,与以上组合如 'rb'
    't' 文本模式(默认)
    '+' 更新(读写),如 'r+'

    # 基本用法
    file = open('example.txt', 'r', encoding='utf-8')
    content = file.read()
    file.close()

    文本模式下,默认编码为平台相关(通常 UTF-8)。强烈建议显式指定 encoding。

    2.2 读取数据

    常用的读取方法:

    • read(size=-1):读取全部或指定字节/字符数。
    • readline():读取一行,含末尾换行符。
    • readlines():读取所有行,返回列表。
    • 直接迭代文件对象本身:「惰性」逐行读取,内存高效。

    # 逐行读取
    with open('data.txt', 'r') as f:
    for line in f:
    print(line.strip())

    readlines() 会一次性将所有行加载到内存,大文件应避免使用。

    2.3 写入数据

    • write(s):写入字符串或字节。
    • writelines(sequence):写入一个字符串序列,不会自动加换行符。

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

    2.4 使用 with 自动管理文件

    with 语句确保文件在任何情况下(包括异常)都能被正确关闭,无需手动调用 close()。这是推荐做法。

    with open('example.txt', 'r') as f:
    data = f.read()
    # 离开 with 块时文件自动关闭


    3. 文件指针与随机访问

    文件对象维护一个当前位置指针,指示下一次读写的位置。

    • tell():返回当前指针位置(字节偏移量)。
    • seek(offset, whence=0):移动指针。
      • whence=0:从头开始(默认)。
      • whence=1:从当前位置。
      • whence=2:从文件末尾。

    with open('data.bin', 'rb') as f:
    f.seek(0, 2) # 移到文件末尾
    size = f.tell() # 获取文件大小
    f.seek(0) # 回到开头
    first_10 = f.read(10)

    文本模式下,seek 的 whence 仅支持 0,且偏移量必须是 tell() 返回的值或 0,因为字符与字节不是一一对应(多字节编码)。


    4. 路径操作:os、os.path 与 pathlib

    4.1 os 模块与 os.path 基础

    os 模块提供许多操作系统功能,os.path 子模块专门处理路径字符串。

    import os

    # 路径拼接(跨平台)
    path = os.path.join('folder', 'sub', 'file.txt')
    # 判断绝对路径
    os.path.isabs(path)
    # 拆分目录与文件名
    dir_name, base_name = os.path.split(path)
    # 获取扩展名
    root, ext = os.path.splitext(base_name)
    # 检查是否存在
    os.path.exists(path)

    这些函数操作的是字符串,不关心路径是否真实存在(除了 exists)。

    4.2 现代路径处理:pathlib.Path

    Python 3.4+ 引入了 pathlib,用面向对象的方式操作路径,代码更直观。

    from pathlib import Path

    # 创建路径对象
    p = Path('documents') / 'report.txt'

    # 常用操作
    p.name # 'report.txt'
    p.stem # 'report'
    p.suffix # '.txt'
    p.parent # Path('documents')
    p.is_file() # 检查是否为文件
    p.is_dir() # 检查是否为目录
    p.exists()

    # 读写整个文件
    content = p.read_text(encoding='utf-8')
    p.write_text('Hello, world!')

    # 遍历目录
    for child in Path('.').iterdir():
    print(child)

    # 递归匹配
    for txt_file in Path('.').rglob('*.txt'):
    print(txt_file)

    推荐在 Python 3.6+ 的项目中优先使用 pathlib,它更符合 Python 风格。


    5. 二进制模式与内存视图

    在二进制模式下(如 'rb', 'wb'),文件操作的对象是 bytes 而非 str。

    with open('image.png', 'rb') as src:
    data = src.read()
    # data 是 bytes 对象
    with open('copy.png', 'wb') as dst:
    dst.write(data)

    处理大型二进制数据时,可以使用 memoryview 实现零拷贝切片。

    with open('data.bin', 'rb') as f:
    buf = memoryview(f.read())
    first_half = buf[:len(buf)//2] # 不复制数据


    6. 序列化:json、pickle 与 csv

    6.1 JSON:通用数据交换格式

    json 模块将 Python 对象与 JSON 字符串相互转换。

    import json

    data = {
    'name': 'Alice',
    'age': 30,
    'skills': ['Python', 'C++']
    }

    # 序列化为字符串
    json_str = json.dumps(data, indent=2, ensure_ascii=False)
    print(json_str)

    # 反序列化
    parsed = json.loads(json_str)

    # 直接与文件交互
    with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2)

    with open('data.json', 'r', encoding='utf-8') as f:
    loaded = json.load(f)

    支持的类型映射:dict → object, list/tuple → array, str → string, int/float → number, True/False → true/false, None → null。自定义对象需要实现编码器。

    6.2 Pickle:Python 原生序列化

    pickle 可以将几乎任意的 Python 对象序列化为字节流,但仅在可信数据间使用,因为反序列化可能执行恶意代码。

    import pickle

    obj = {'key': [1, 2, 3], 'set': {4, 5}}

    # 序列化
    with open('obj.pkl', 'wb') as f:
    pickle.dump(obj, f)

    # 反序列化
    with open('obj.pkl', 'rb') as f:
    restored = pickle.load(f)

    # 也可以生成字节串
    data = pickle.dumps(obj)

    pickle 不是跨语言的,且与 Python 版本绑定较紧,长期存储考虑使用 JSON 或其他标准格式。

    6.3 CSV:逗号分隔值处理

    csv 模块处理 CSV 文件。

    import csv

    # 读取
    with open('data.csv', 'r', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
    print(row)

    # 写入
    with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['Name', 'Age'])
    writer.writerow(['Alice', 30])

    对于字典式操作,使用 csv.DictReader 和 csv.DictWriter 更方便。

    with open('data.csv', 'r') as f:
    reader = csv.DictReader(f)
    for row in reader:
    print(row['Name'])

    注意:打开 CSV 文件时,推荐用 newline='' 避免平台换行符差异。


    7. 内存中的虚拟文件:StringIO 与 BytesIO

    io.StringIO 和 io.BytesIO 在内存中模拟文本和二进制流,常用于测试或临时缓冲。

    from io import StringIO, BytesIO

    # 文本流
    sio = StringIO()
    sio.write('Hello\\n')
    sio.write('World')
    print(sio.getvalue()) # 'Hello\\nWorld'
    sio.close()

    # 像文件一样读取
    sio = StringIO('第一行\\n第二行')
    for line in sio:
    print(line.strip())

    # 二进制流
    bio = BytesIO()
    bio.write(b'\\x00\\x01\\x02')
    bio.seek(0)
    print(bio.read()) # b'\\x00\\x01\\x02'


    8. 编码与解码深度解析

    字符编码是将字符映射为字节的方案。Python 内部使用 Unicode,文件 I/O 需要编解码。

    • 编码:将字符串转为字节 '你好'.encode('utf-8') → b'\\xe4\\xbd\\xa0\\xe5\\xa5\\xbd'
    • 解码:将字节转为字符串 b'\\xe4\\xbd\\xa0\\xe5\\xa5\\xbd'.decode('utf-8') → '你好'

    常见编码:

    编码特点
    ASCII 仅英文字母和符号,单字节
    UTF-8 可变长度,向后兼容 ASCII,国际通用
    GBK 中文编码
    Latin-1 西欧语言,单字节

    打开文件时,务必指定正确的 encoding 参数,否则使用平台默认编码,可能产生乱码或错误。

    # 读取 GBK 编码文件
    with open('gbk_file.txt', 'r', encoding='gbk') as f:
    text = f.read()

    # 写入 UTF-8 文件
    with open('utf8_file.txt', 'w', encoding='utf-8') as f:
    f.write('包含中文字符')

    当编解码出错时,可通过 errors 参数控制行为:'strict'(默认,抛异常)、'ignore'(忽略)、'replace'(用 ? 替换)。


    9. 高级文件处理

    9.1 目录遍历:os.walk 与 pathlib.rglob

    • os.walk 递归遍历目录树,返回 (dirpath, dirnames, filenames) 三元组。
    • pathlib.rglob(pattern) 更简洁。

    import os
    for root, dirs, files in os.walk('.'):
    for name in files:
    print(os.path.join(root, name))

    from pathlib import Path
    for py_file in Path('.').rglob('*.py'):
    print(py_file.absolute())

    9.2 文件系统操作:拷贝、移动、删除

    shutil 模块提供高层次的文件操作。

    import shutil

    # 拷贝文件
    shutil.copy('src.txt', 'dst.txt')
    # 拷贝目录树
    shutil.copytree('src_dir', 'dst_dir')
    # 移动文件或目录
    shutil.move('old', 'new')
    # 删除目录树
    shutil.rmtree('dir')

    基本删除/创建目录可使用 os.remove()、os.mkdir() 等。

    9.3 临时文件与目录:tempfile

    tempfile 用于安全创建临时文件/目录,自动删除。

    import tempfile

    # 创建临时文件
    with tempfile.NamedTemporaryFile(mode='w+t', suffix='.txt', delete=True) as tmp:
    tmp.write('临时内容')
    tmp.seek(0)
    print(tmp.read())
    # 文件自动删除

    # 创建临时目录
    with tempfile.TemporaryDirectory() as tmpdir:
    print(tmpdir)
    # 目录自动删除


    10. 常见陷阱与最佳实践

    • 编码未指定:总是为文本模式指定 encoding='utf-8',避免跨平台问题。
    • 大文件一次性读入内存:对大型文件使用逐行迭代或指定块大小读取。
    • 忘记关闭文件:使用 with 语句。
    • 路径字符串拼接直用 +:使用 os.path.join 或 pathlib.Path / 操作符。
    • readlines 遍历大文件:改用 for line in file。
    • pickle 加载不安全数据:绝不从不受信任的来源用 pickle.load。
    • 文本模式 seek:文本模式下的 seek 受限于字符偏移,尽量在二进制模式进行随机访问。
    • CSV 文件中缺少 newline='':会导致在 Windows 平台下出现多余的空白行。

    11. 总结

    Python 的 I/O 体系涵盖从底层文件操作到高级序列化与路径处理的方方面面。核心要点:

    • 使用 with 进行文件管理,规避资源泄露。
    • 优先选用 pathlib.Path 进行路径操作,提升可读性。
    • 根据数据特点选择序列化格式:通用选 JSON,Python 内部临时用 Pickle,表格数据选 CSV。
    • 文本 I/O 必须关注编码;二进制 I/O 则处理 bytes。

    掌握这些技术,你就能高效、安全地进行文件处理,为数据处理、日志系统、配置管理等应用打下坚实基础。

    赞(0)
    未经允许不得转载:171主机测评 » 9. Python 文件与输入输出 深度解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址