查看: 144|回复: 3

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

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
Python的文件操作是日常脚本开发中最常见的需求之一,无论读取配置、处理日志、导出数据还是实现本地持久化,都离不开文件读写。本文从基础API到高级用法,结合实际案例梳理Python文件操作的核心知识点。
  1. 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',避免跨平台乱码。
  1. # 示例:不同模式的with写法
  2. with open('config.ini', 'r', encoding='utf-8') as f:
  3.     content = f.read()
  4. with open('output.txt', 'w', encoding='utf-8') as f:
  5.     f.write('新内容\n')
  6. with open('app.log', 'a', encoding='utf-8') as f:
  7.     f.write('2026-06-26: 启动\n')
  8. with open('image.jpg', 'rb') as f:
  9.     data = f.read()
复制代码

二、文件读取的四种方式
1. read(size):一次性读取全部(指定字节数),适合小文件。
2. readline():读取一行,适合逐行处理且需保留行号场景。
3. readlines():返回列表,每行为一个元素,大文件慎用。
4. 直接迭代file object:最内存友好,逐行读取,占用恒定内存,推荐用于大日志文件。
  1. with open('server.log', 'r', encoding='utf-8') as f:
  2.     for line in f:
  3.         if 'ERROR' in line:
  4.             error_count += 1
复制代码

三、写入方法
- write(str):写入字符串,需手动添加换行符'\n'。
- writelines(iterable):写入多个字符串,不会自动换行,元素需自带换行符。
  1. lines = ['苹果\n', '香蕉\n', '橙子\n']
  2. with open('fruits.txt', 'w', encoding='utf-8') as f:
  3.     f.writelines(lines)
复制代码

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

同时打开多个文件:
  1. with open('src.txt', 'r', encoding='utf-8') as src, \
  2.      open('dst.txt', 'w', encoding='utf-8') as dst:
  3.     dst.write(src.read())
复制代码

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

实战:读取文件头部和尾部。
  1. with open('large.dat', 'rb') as f:
  2.     first_10 = f.read(10)
  3.     f.seek(-10, 2)  # 从末尾往回10字节
  4.     last_10 = f.read(10)
复制代码

六、异常处理
常见异常:FileNotFoundError、PermissionError、IOError。建议用try-except包裹文件操作,尤其是读取外部文件时。
  1. try:
  2.     with open('config.txt', 'r', encoding='utf-8') as f:
  3.         content = f.read()
  4. except FileNotFoundError:
  5.     print('文件不存在')
  6. except PermissionError:
  7.     print('无权限')
  8. except IOError as e:
  9.     print(f'I/O错误:{e}')
复制代码

七、编码处理
Python 3默认编码UTF-8,但实际环境可能遇到GBK等。指定encoding即可,错误处理可用errors='ignore'或'replace'。
自动检测编码推荐chardet库:
  1. import chardet
  2. with open('unknown.txt', 'rb') as f:
  3.     raw = f.read()
  4. result = chardet.detect(raw)
  5. encoding = result['encoding']
  6. with open('unknown.txt', 'r', encoding=encoding) as f:
  7.     content = f.read()
复制代码

八、二进制文件与大文件分块复制
二进制模式用于图片、视频等非文本文件。大文件应分块读写避免内存溢出:
  1. chunk_size = 4096
  2. with open('source.mp4', 'rb') as src, open('copy.mp4', 'wb') as dst:
  3.     while True:
  4.         chunk = src.read(chunk_size)
  5.         if not chunk:
  6.             break
  7.         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模块:
  1. import csv
  2. # 写入
  3. with open('people.csv', 'w', newline='', encoding='utf-8') as f:
  4.     writer = csv.writer(f)
  5.     writer.writerows([['姓名', '年龄'], ['张三', 25]])
  6. # 读取
  7. with open('people.csv', 'r', encoding='utf-8') as f:
  8.     reader = csv.reader(f)
  9.     for row in reader:
  10.         print(row)
复制代码
DictWriter/DictReader可直接操作字典:
  1. with open('people_dict.csv', 'w', newline='', encoding='utf-8') as f:
  2.     fieldnames = ['name', 'age']
  3.     writer = csv.DictWriter(f, fieldnames=fieldnames)
  4.     writer.writeheader()
  5.     writer.writerows([{'name':'张三','age':25}, {'name':'李四','age':30}])
复制代码

十一、JSON读写
json模块对接字典/列表:
  1. import json
  2. data = {'name': '张三', 'age': 25, 'hobbies': ['阅读', '编程']}
  3. with open('data.json', 'w', encoding='utf-8') as f:
  4.     json.dump(data, f, ensure_ascii=False, indent=4)
  5. with open('data.json', 'r', encoding='utf-8') as f:
  6.     loaded = json.load(f)
复制代码
字符串互转用json.dumps()/json.loads()。

十二、临时文件与目录
tempfile模块:
  1. import tempfile
  2. with tempfile.TemporaryFile(mode='w+t') as tf:
  3.     tf.write('临时数据')
  4.     tf.seek(0)
  5.     print(tf.read())
  6. # 离开with自动删除
复制代码
NamedTemporaryFile可保留文件名,TemporaryDirectory创建临时目录。

十三、综合实战案例
案例1:日志分析器
  1. def analyze_log(log_file, error_output):
  2.     error_lines = []
  3.     try:
  4.         with open(log_file, 'r', encoding='utf-8') as f:
  5.             for line in f:
  6.                 if 'ERROR' in line.upper():
  7.                     error_lines.append(line.strip())
  8.         with open(error_output, 'w', encoding='utf-8') as f:
  9.             f.write(f'共发现 {len(error_lines)} 个错误:\n')
  10.             f.writelines([line + '\n' for line in error_lines])
  11.         print(f'分析完成,结果保存至{error_output}')
  12.     except FileNotFoundError:
  13.         print('日志文件不存在')
  14.     except PermissionError:
  15.         print('无权限读取')
复制代码

案例2:学生成绩管理系统(JSON持久化)
  1. import json, os
  2. class StudentManager:
  3.     def __init__(self, data_file='students.json'):
  4.         self.data_file = data_file
  5.         self.students = []
  6.         self.load_data()
  7.     def load_data(self):
  8.         if os.path.exists(self.data_file):
  9.             with open(self.data_file, 'r', encoding='utf-8') as f:
  10.                 self.students = json.load(f)
  11.         else:
  12.             self.students = []
  13.     def save_data(self):
  14.         with open(self.data_file, 'w', encoding='utf-8') as f:
  15.             json.dump(self.students, f, ensure_ascii=False, indent=2)
复制代码

案例3:文件批量重命名
  1. import os
  2. def batch_rename(dir_path, prefix='file', ext='.txt'):
  3.     for i, fname in enumerate(os.listdir(dir_path)):
  4.         src = os.path.join(dir_path, fname)
  5.         if os.path.isfile(src):
  6.             dst = os.path.join(dir_path, f'{prefix}_{i}{ext}')
  7.             os.rename(src, dst)
复制代码

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

使用道具 举报

发表于 2 小时前 | 显示全部楼层

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

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

使用道具 举报

发表于 2 小时前 | 显示全部楼层

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

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

使用道具 举报

发表于 2 小时前 | 显示全部楼层

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

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

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-10 12:56 , Processed in 0.034547 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部