脚本专家 发表于 3 天前

Python文件操作实战:open、with、seek、CSV/JSON

Python的文件操作是日常脚本开发中最常见的需求之一,无论读取配置、处理日志、导出数据还是实现本地持久化,都离不开文件读写。本文从基础API到高级用法,结合实际案例梳理Python文件操作的核心知识点。


import os, json, csv, shutil, tempfile, chardet


一、打开文件的两种模式
内置函数open()是文件操作的入口,语法:open(file, mode='r', encoding=None, buffering=-1)。

常见mode参数:
- 'r':只读,文件必须存在(默认)。
- 'w':覆盖写入,不存在则创建。
- 'a':追加写入,不存在则创建。
- 'x':独占创建,文件已存在则抛异常FileExistsError。
- 'r+'/'w+'/'a+':读写组合,其中r+不截断文件,w+会截断,a+追加且可读。
- 'b':二进制模式,需与r/w/a组合(如'rb')。
- 't':文本模式(默认)。

推荐始终指定encoding='utf-8',避免跨平台乱码。


# 示例:不同模式的with写法
with open('config.ini', 'r', encoding='utf-8') as f:
    content = f.read()
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('新内容\n')
with open('app.log', 'a', encoding='utf-8') as f:
    f.write('2026-06-26: 启动\n')
with open('image.jpg', 'rb') as f:
    data = f.read()


二、文件读取的四种方式
1. read(size):一次性读取全部(指定字节数),适合小文件。
2. readline():读取一行,适合逐行处理且需保留行号场景。
3. readlines():返回列表,每行为一个元素,大文件慎用。
4. 直接迭代file object:最内存友好,逐行读取,占用恒定内存,推荐用于大日志文件。


with open('server.log', 'r', encoding='utf-8') as f:
    for line in f:
      if 'ERROR' in line:
            error_count += 1


三、写入方法
- write(str):写入字符串,需手动添加换行符'\n'。
- writelines(iterable):写入多个字符串,不会自动换行,元素需自带换行符。


lines = ['苹果\n', '香蕉\n', '橙子\n']
with open('fruits.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)


四、with语句与上下文管理器
传统open+close存在忘记关闭或异常时未释放资源的风险。with语句通过上下文管理器自动调用__exit__,确保文件被正确关闭,即使发生异常。

同时打开多个文件:

with open('src.txt', 'r', encoding='utf-8') as src, \
   open('dst.txt', 'w', encoding='utf-8') as dst:
    dst.write(src.read())


五、文件指针控制:seek()与tell()
- tell():返回当前指针位置(字节数)。
- seek(offset, whence):移动指针。whence=0(开头,默认)、1(当前位置)、2(末尾)。注意:文本模式下只允许从开头定位,二进制模式可自由移动。

实战:读取文件头部和尾部。

with open('large.dat', 'rb') as f:
    first_10 = f.read(10)
    f.seek(-10, 2)# 从末尾往回10字节
    last_10 = f.read(10)


六、异常处理
常见异常:FileNotFoundError、PermissionError、IOError。建议用try-except包裹文件操作,尤其是读取外部文件时。


try:
    with open('config.txt', 'r', encoding='utf-8') as f:
      content = f.read()
except FileNotFoundError:
    print('文件不存在')
except PermissionError:
    print('无权限')
except IOError as e:
    print(f'I/O错误:{e}')


七、编码处理
Python 3默认编码UTF-8,但实际环境可能遇到GBK等。指定encoding即可,错误处理可用errors='ignore'或'replace'。
自动检测编码推荐chardet库:

import chardet
with open('unknown.txt', 'rb') as f:
    raw = f.read()
result = chardet.detect(raw)
encoding = result['encoding']
with open('unknown.txt', 'r', encoding=encoding) as f:
    content = f.read()


八、二进制文件与大文件分块复制
二进制模式用于图片、视频等非文本文件。大文件应分块读写避免内存溢出:

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


九、os与shutil模块
os模块负责文件/目录操作:
- os.getcwd()、os.listdir()、os.rename()、os.remove()、os.path.exists()等。
- os.mkdir()创建单级目录,os.makedirs()创建多级目录。
- os.path.join()跨平台拼接路径,os.path.basename()/dirname(),os.path.splitext()分离扩展名。

shutil提供高级操作:
- shutil.copy()/copy2()复制文件(copy2保留元数据)。
- shutil.copytree()递归复制目录。
- shutil.move()移动文件/目录。
- shutil.rmtree()删除非空目录树(谨慎)。

十、CSV读写
内置csv模块:

import csv
# 写入
with open('people.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerows([['姓名', '年龄'], ['张三', 25]])
# 读取
with open('people.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
      print(row)

DictWriter/DictReader可直接操作字典:

with open('people_dict.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ['name', 'age']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows([{'name':'张三','age':25}, {'name':'李四','age':30}])


十一、JSON读写
json模块对接字典/列表:

import json
data = {'name': '张三', 'age': 25, 'hobbies': ['阅读', '编程']}
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
with open('data.json', 'r', encoding='utf-8') as f:
    loaded = json.load(f)

字符串互转用json.dumps()/json.loads()。

十二、临时文件与目录
tempfile模块:

import tempfile
with tempfile.TemporaryFile(mode='w+t') as tf:
    tf.write('临时数据')
    tf.seek(0)
    print(tf.read())
# 离开with自动删除

NamedTemporaryFile可保留文件名,TemporaryDirectory创建临时目录。

十三、综合实战案例
案例1:日志分析器

def analyze_log(log_file, error_output):
    error_lines = []
    try:
      with open(log_file, 'r', encoding='utf-8') as f:
            for line in f:
                if 'ERROR' in line.upper():
                  error_lines.append(line.strip())
      with open(error_output, 'w', encoding='utf-8') as f:
            f.write(f'共发现 {len(error_lines)} 个错误:\n')
            f.writelines()
      print(f'分析完成,结果保存至{error_output}')
    except FileNotFoundError:
      print('日志文件不存在')
    except PermissionError:
      print('无权限读取')


案例2:学生成绩管理系统(JSON持久化)

import json, os
class StudentManager:
    def __init__(self, data_file='students.json'):
      self.data_file = data_file
      self.students = []
      self.load_data()
    def load_data(self):
      if os.path.exists(self.data_file):
            with open(self.data_file, 'r', encoding='utf-8') as f:
                self.students = json.load(f)
      else:
            self.students = []
    def save_data(self):
      with open(self.data_file, 'w', encoding='utf-8') as f:
            json.dump(self.students, f, ensure_ascii=False, indent=2)


案例3:文件批量重命名

import os
def batch_rename(dir_path, prefix='file', ext='.txt'):
    for i, fname in enumerate(os.listdir(dir_path)):
      src = os.path.join(dir_path, fname)
      if os.path.isfile(src):
            dst = os.path.join(dir_path, f'{prefix}_{i}{ext}')
            os.rename(src, dst)


总结
文件操作核心三要素:打开、读写、关闭。务必使用with语句,指定编码,处理异常。根据文件大小选择合适的读取方式,二进制文件分块操作,熟悉os/shutil进行路径和目录管理。掌握CSV/JSON序列化后即可应对大部分数据持久化场景。

热心网友4 发表于 3 天前

Re: Python文件操作实战:open、with、seek、CSV/JSON

楼主这篇整理得非常全面,从基础 mode 到 with 语句、seek、编码检测都覆盖到了,尤其是二进制分块复制的 chunk 写法,对处理大文件很实用。另外提个小点:文本模式下 seek 相对位置(1 和 2)在 Python 3 里会抛异常,只能用于二进制,文章里已经点了,正好提醒大家注意。难得看到这么扎实的总结,谢谢分享。

热心网友4 发表于 3 天前

Re: Python文件操作实战:open、with、seek、CSV/JSON

感谢楼主分享!这篇总结非常全面,从基础 API 到异常处理、编码检测、大文件复制都覆盖了,特别适合新手系统学习。我个人比较喜欢 seek 定位和 chardet 自动检测编码这两个实战技巧,平时处理格式混乱的日志文件时很管用。另外,如果经常操作路径,可以考虑用 `pathlib` 模块(Python 3.4+),它用 Path 对象替代字符串拼接,可读性和跨平台兼容性会更好一些。再次感谢,收藏了!

热心网友4 发表于 3 天前

Re: Python文件操作实战:open、with、seek、CSV/JSON

感谢分享!很全面的Python文件操作指南,尤其是seek文件指针控制和with多文件同时打开的写法,日常确实很实用。我平时处理大日志文件时常用直接迭代文件对象,内存占用确实低。另外想问一下,关于chardet自动检测编码,如果遇到混合编码的文件(比如同一文件里既有UTF-8又有GBK),有什么好的处理思路吗?再次感谢楼主的整理!
页: [1]
查看完整版本: Python文件操作实战:open、with、seek、CSV/JSON