Python文件读写与数据处理实战:文本、CSV、JSON、目录遍历与批量处理

前面我们已经学习了 Python 的基础语法、函数、模块、面向对象、错误处理,以及常用标准库。

如果说前面的内容更多是在打语言基础,那么从这一篇开始,我们就更进一步进入“真实任务怎么做”这个层面。

因为在实际开发中,很多 Python 程序的工作都离不开下面这些事情:

  • 读取文本文件;
  • 写入处理结果;
  • 批量遍历目录;
  • 处理 CSV 数据;
  • 读写 JSON 配置;
  • 清洗原始数据;
  • 把多个小步骤串成一个自动化脚本。

也就是说,很多时候 Python 不是只在“写算法”,而是在做:

和文件打交道、和数据打交道、和批量任务打交道。

这也是为什么“文件读写与数据处理”是 Python 学习中非常关键的一步。

本文会围绕实际开发中最常见的几个方向展开:

  • 文本文件的读取与写入;
  • 文件路径与目录遍历;
  • CSV 文件处理;
  • JSON 文件处理;
  • 批量文件处理思路;
  • 常见错误与实战建议。

理解这一章之后,你会发现自己已经能写出很多非常实用的小工具了,例如:

  • 批量整理文件;
  • 统计日志信息;
  • 清洗导出的表格数据;
  • 合并多个配置文件;
  • 自动生成处理报告。

一、为什么文件读写这么重要?

很多初学者刚开始写 Python 时,程序数据都来自:

  • 代码里手写的变量;
  • 命令行输入;
  • 一次性的小例子。

但真实开发里,数据往往不会凭空出现在程序中。

它更常来自:

  • 本地文本文件;
  • 配置文件;
  • 接口导出的 JSON;
  • Excel 或 CSV 导出的报表;
  • 某个目录中的大量文件;
  • 日志文件。

所以只会写:

1
2
name = 'Alice'
score = 95

是远远不够的。

更关键的是学会:

  • 数据怎么从文件里读进来;
  • 处理后怎么再写回去;
  • 如果有几十个、几百个文件,该怎么批量做。

这正是这一篇的重点。


二、文本文件读取:最基础也最常见的操作

2.1 open() 的基本用法

Python 最基础的文件读取方式,就是使用 open()

1
2
3
with open('hello.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)

这里有几个关键点:

  • 'r' 表示只读模式;
  • encoding='utf-8' 表示按 UTF-8 编码读取文本;
  • with 可以确保文件在使用后自动关闭。

初学阶段请尽量养成一个习惯:

只要是文件操作,优先使用 with open(...)

2.2 为什么要显式写 encoding

因为文本文件本质上是字节数据,不同系统、不同工具保存出来的编码可能不一样。

如果你不写编码,程序有时会:

  • 在某些环境下正常;
  • 到另一个环境就报错;
  • 或者读出来变成乱码。

所以对于中文文本,最稳妥的习惯通常是:

1
encoding='utf-8'
2.3 read()readline() 和按行遍历

常见的读取方式有三种。

(1)一次读完整个文件:read()
1
2
with open('notes.txt', 'r', encoding='utf-8') as f:
text = f.read()

适合:

  • 文件比较小;
  • 需要整体处理全文内容。
(2)读一行:readline()
1
2
3
with open('notes.txt', 'r', encoding='utf-8') as f:
first_line = f.readline()
print(first_line)

适合:

  • 只关心前几行;
  • 处理带标题的文本文件。
(3)按行遍历
1
2
3
with open('notes.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line.strip())

这通常是最实用的方式之一,因为:

  • 内存更省;
  • 很适合日志文件、数据文件;
  • 可以边读边处理。
2.4 strip() 的作用

很多人在按行读文件时都会遇到“多出一个空行”的现象。

原因通常是每一行末尾本身就带有换行符 \n

1
line.strip()

可以帮助去掉首尾空白字符,在很多文本处理场景里非常常用。

不过也要注意:

  • 如果你需要保留原始格式,就不要随便 strip()
  • 如果只是做清洗、统计、解析,通常可以用。

三、文本文件写入:把处理结果保存下来

3.1 最基本的写入方式
1
2
with open('output.txt', 'w', encoding='utf-8') as f:
f.write('Hello, Python!')

这里:

  • 'w' 表示写入模式;
  • 如果文件不存在,会创建;
  • 如果文件已存在,原内容通常会被覆盖。
3.2 追加写入:a 模式

如果你不想覆盖原文件,而是想在末尾继续追加内容,可以使用:

1
2
with open('log.txt', 'a', encoding='utf-8') as f:
f.write('新增一条日志\n')

这在下面这些场景里很常见:

  • 写运行日志;
  • 逐步记录处理结果;
  • 累积导出信息。
3.3 写多行内容
1
2
3
4
lines = ['第一行\n', '第二行\n', '第三行\n']

with open('output.txt', 'w', encoding='utf-8') as f:
f.writelines(lines)

需要注意:

writelines() 不会自动帮你补换行符。

所以每一行结尾的 \n 通常需要你自己加上。

3.4 使用 print(..., file=f)

除了 write(),还有一种很自然的写法:

1
2
3
4
with open('report.txt', 'w', encoding='utf-8') as f:
print('处理结果报告', file=f)
print('总数:100', file=f)
print('成功:98', file=f)

这种方式很适合:

  • 生成报告;
  • 写结构简单的文本;
  • 快速输出格式化结果。

四、pathlib:更推荐的路径处理方式

前一篇我们已经接触过 pathlib,这一篇会更强调它在文件处理实战中的价值。

4.1 用 Path 表示文件路径
1
2
3
4
from pathlib import Path

path = Path('data') / 'users.txt'
print(path)

这比字符串拼路径更自然,也更不容易出错。

4.2 读取与写入文本

Path 直接提供了简洁方法:

1
2
3
4
5
6
from pathlib import Path

path = Path('hello.txt')
path.write_text('Hello, Python!', encoding='utf-8')
content = path.read_text(encoding='utf-8')
print(content)

如果只是简单读写文本,这种写法非常方便。

4.3 判断文件是否存在
1
2
3
4
5
6
7
from pathlib import Path

path = Path('config.json')
if path.exists():
print('文件存在')
else:
print('文件不存在')
4.4 创建目录
1
2
3
4
from pathlib import Path

output_dir = Path('output')
output_dir.mkdir(exist_ok=True)

如果需要递归创建多级目录:

1
output_dir.mkdir(parents=True, exist_ok=True)

这在批量输出处理结果时很常用。


五、目录遍历:批量处理的起点

很多时候,我们不是处理一个文件,而是处理一个目录中的很多文件。

5.1 遍历当前目录内容
1
2
3
4
from pathlib import Path

for item in Path('.').iterdir():
print(item)
5.2 只找某种类型的文件:glob()
1
2
3
4
from pathlib import Path

for txt_file in Path('data').glob('*.txt'):
print(txt_file)

这表示只找 data 目录下的 .txt 文件。

5.3 递归查找:rglob()
1
2
3
4
from pathlib import Path

for py_file in Path('.').rglob('*.py'):
print(py_file)

这会递归搜索所有子目录。

5.4 一个批量统计文本文件行数的示例
1
2
3
4
5
6
from pathlib import Path

for txt_file in Path('data').glob('*.txt'):
with txt_file.open('r', encoding='utf-8') as f:
line_count = sum(1 for _ in f)
print(txt_file.name, line_count)

这个例子非常典型:

  • 先找文件;
  • 再逐个处理;
  • 最后输出统计结果。

很多自动化脚本,本质上都是这个模式的延伸。


六、二进制文件:图片、压缩包、音频等怎么处理?

前面讲的是文本文件,它们需要编码解码。

但像下面这些文件:

  • 图片;
  • PDF;
  • 压缩包;
  • 音频;
  • 视频;

通常不应该按文本方式读取,而应该按二进制模式处理。

6.1 二进制读取:rb
1
2
3
with open('image.png', 'rb') as f:
data = f.read()
print(len(data))
6.2 二进制写入:wb
1
2
with open('copy.bin', 'wb') as f:
f.write(data)
6.3 Path 里的二进制方法
1
2
3
4
5
from pathlib import Path

path = Path('image.png')
data = path.read_bytes()
Path('copy.png').write_bytes(data)

学习阶段你至少要知道:

  • 文本文件用 r / w
  • 二进制文件用 rb / wb
  • 不要拿图片去按 utf-8 文本读取。

七、CSV 文件处理:表格数据最常见的格式之一

CSV 是非常常见的数据交换格式,尤其在:

  • Excel 导出;
  • 数据报表;
  • 简单数据清洗;
  • 跨系统传输结构化表格数据。

Python 标准库中有专门的 csv 模块。

7.1 读取 CSV:csv.reader
1
2
3
4
5
6
import csv

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

每一行通常会被读成一个列表。

7.2 使用 csv.DictReader

实际开发里,更常用的是 DictReader,因为它会根据表头返回字典,代码更容易读。

1
2
3
4
5
6
import csv

with open('students.csv', 'r', encoding='utf-8', newline='') as f:
reader = csv.DictReader(f)
for row in reader:
print(row['name'], row['score'])

这比用下标 row[0]row[1] 更直观。

7.3 写入 CSV:csv.writer
1
2
3
4
5
6
7
8
9
10
11
import csv

rows = [
['name', 'score'],
['Alice', 95],
['Bob', 88],
]

with open('result.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerows(rows)
7.4 写入 CSV:csv.DictWriter
1
2
3
4
5
6
7
8
9
10
11
12
import csv

rows = [
{'name': 'Alice', 'score': 95},
{'name': 'Bob', 'score': 88},
]

with open('result.csv', 'w', encoding='utf-8', newline='') as f:
fieldnames = ['name', 'score']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
7.5 为什么 newline='' 很重要?

处理 CSV 时,标准写法里常常会写:

1
newline=''

这是为了避免某些平台下出现空行问题。

所以你以后看到 CSV 示例里带这个参数,不要觉得多余。

7.6 一个简单的数据筛选示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import csv

passed_students = []

with open('students.csv', 'r', encoding='utf-8', newline='') as f:
reader = csv.DictReader(f)
for row in reader:
if int(row['score']) >= 60:
passed_students.append(row)

with open('passed_students.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['name', 'score'])
writer.writeheader()
writer.writerows(passed_students)

这已经是一个很真实的数据处理脚本雏形了。


八、JSON 文件处理:结构化数据交换的核心格式

JSON 在现代开发里非常常见。

8.1 读取 JSON 文件
1
2
3
4
5
import json

with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
print(config)
8.2 写入 JSON 文件
1
2
3
4
5
6
7
8
9
10
import json

config = {
'debug': True,
'port': 8080,
'hosts': ['127.0.0.1', '0.0.0.0']
}

with open('config.json', 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=2)

这里:

  • ensure_ascii=False 可以避免中文被转成转义形式;
  • indent=2 让文件更易读。
8.3 JSON 和 CSV 的区别怎么理解?

可以简单这样区分:

  • CSV 更适合规则表格;
  • JSON 更适合层级结构数据。

例如学生成绩表适合 CSV,而配置文件、接口响应更适合 JSON。

8.4 一个配置文件更新示例
1
2
3
4
5
6
7
import json
from pathlib import Path

path = Path('config.json')
config = json.loads(path.read_text(encoding='utf-8'))
config['debug'] = False
path.write_text(json.dumps(config, ensure_ascii=False, indent=2), encoding='utf-8')

这个例子体现了一种常见流程:

  • 先读取;
  • 再修改;
  • 最后覆盖写回。

九、数据清洗:文件处理里最常见的真实任务

读写文件本身只是手段,很多真实任务的核心其实是“清洗数据”。

例如:

  • 去掉空行;
  • 去掉多余空格;
  • 统一大小写;
  • 去重;
  • 过滤非法值;
  • 重新组织字段格式。
9.1 去掉空行和首尾空白
1
2
3
4
5
6
7
clean_lines = []

with open('raw.txt', 'r', encoding='utf-8') as f:
for line in f:
text = line.strip()
if text:
clean_lines.append(text)
9.2 去重并保持顺序
1
unique_lines = list(dict.fromkeys(clean_lines))
9.3 写入清洗结果
1
2
3
with open('clean.txt', 'w', encoding='utf-8') as f:
for line in unique_lines:
f.write(line + '\n')
9.4 一个完整的文本清洗示例
1
2
3
4
5
6
7
8
9
10
11
12
13
from pathlib import Path

source = Path('raw.txt')
target = Path('clean.txt')

clean_lines = []
for line in source.read_text(encoding='utf-8').splitlines():
text = line.strip()
if text:
clean_lines.append(text)

unique_lines = list(dict.fromkeys(clean_lines))
target.write_text('\n'.join(unique_lines) + '\n', encoding='utf-8')

这个脚本做了几件很常见的事:

  • 读原始文本;
  • 清理空白;
  • 去掉空行;
  • 去重;
  • 写回新文件。

这已经非常接近很多实际工作中的“小工具脚本”了。


十、批量处理:真正提高效率的关键

Python 在办公自动化、数据处理里最有价值的地方之一,就是批量处理。

10.1 一个批量统计目录中文件大小的示例
1
2
3
4
5
from pathlib import Path

for file_path in Path('data').glob('*'):
if file_path.is_file():
print(file_path.name, file_path.stat().st_size)
10.2 一个批量重命名示例
1
2
3
4
5
6
from pathlib import Path

for index, file_path in enumerate(Path('images').glob('*.png'), start=1):
new_name = f'image_{index:03d}.png'
new_path = file_path.with_name(new_name)
file_path.rename(new_path)

这个例子很典型,但真实使用时一定要小心,因为它会直接修改文件名。

10.3 一个批量合并文本文件示例
1
2
3
4
5
6
7
8
from pathlib import Path

output_lines = []
for txt_file in Path('articles').glob('*.txt'):
output_lines.append(f'### {txt_file.name}')
output_lines.append(txt_file.read_text(encoding='utf-8'))

Path('merged.txt').write_text('\n\n'.join(output_lines), encoding='utf-8')
10.4 批量处理的通用思路

很多批量任务都可以套用同一个模型:

  1. 找到目标文件;
  2. 逐个读取;
  3. 做转换或清洗;
  4. 输出结果;
  5. 记录成功和失败。

也就是说,真正重要的不是死记某个具体脚本,而是掌握这种通用流程。


十一、文件复制、移动与删除:shutil 的作用

如果只是读写文本,open()Path 已经足够。

但如果你需要:

  • 复制文件;
  • 复制目录;
  • 移动文件;
  • 删除目录树;

那么 shutil 就很有用。

11.1 复制文件
1
2
3
import shutil

shutil.copy('source.txt', 'backup.txt')
11.2 移动文件
1
2
3
import shutil

shutil.move('old.txt', 'archive/old.txt')
11.3 复制整个目录
1
2
3
import shutil

shutil.copytree('source_dir', 'backup_dir')
11.4 删除整个目录
1
2
3
import shutil

shutil.rmtree('temp_dir')

这类操作要特别谨慎,因为删除和覆盖往往不可逆。


十二、错误处理:文件操作最容易踩的坑

文件处理是最容易遇到异常的场景之一。

12.1 文件不存在
1
2
3
4
5
try:
with open('not_exist.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('文件不存在')
12.2 编码错误

如果文件不是 UTF-8 编码,可能会触发解码异常。

这时你需要:

  • 确认原文件编码;
  • 或者换成正确编码方式重新读取。
12.3 权限不足

有时即使文件存在,也可能因为权限不足无法读取或写入。

12.4 不要一上来就把所有异常吞掉

错误示例:

1
2
3
4
try:
do_something()
except:
pass

这会让你失去定位问题的机会。

更好的做法是:

  • 捕获明确异常;
  • 输出或记录错误信息;
  • 必要时保留失败文件列表。
12.5 批量处理时的容错思路

例如:

1
2
3
4
5
6
7
8
from pathlib import Path

for file_path in Path('data').glob('*.txt'):
try:
content = file_path.read_text(encoding='utf-8')
print(file_path.name, len(content))
except Exception as e:
print(f'{file_path.name} 处理失败: {e}')

这在批量场景里非常常见:

  • 单个文件失败,不影响其他文件继续处理;
  • 最后再统一检查失败项。

十三、一个综合示例:批量清洗 CSV 并导出 JSON

下面用一个稍微完整一点的例子,把前面的思路串起来。

假设有一个 students.csv 文件,内容类似:

1
2
3
4
5
name,score
Alice,95
Bob,88
Cindy,59
David,72

现在我们要做几件事:

  • 读取 CSV;
  • 筛出及格学生;
  • 把结果保存成 JSON;
  • 同时输出一份简单报告。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import csv
import json
from pathlib import Path

source = Path('students.csv')
json_output = Path('passed_students.json')
report_output = Path('report.txt')

passed_students = []

with source.open('r', encoding='utf-8', newline='') as f:
reader = csv.DictReader(f)
for row in reader:
score = int(row['score'])
if score >= 60:
passed_students.append({
'name': row['name'].strip(),
'score': score,
})

json_output.write_text(
json.dumps(passed_students, ensure_ascii=False, indent=2),
encoding='utf-8'
)

with report_output.open('w', encoding='utf-8') as f:
print('成绩处理报告', file=f)
print(f'总及格人数:{len(passed_students)}', file=f)
for student in passed_students:
print(f"- {student['name']}: {student['score']}", file=f)

这个例子虽然不复杂,但已经体现了很多真实技能:

  • 路径处理;
  • CSV 读取;
  • 数据清洗;
  • JSON 输出;
  • 文本报告生成。

而这正是 Python 在日常自动化工作里最常见的价值体现。


十四、学习建议:这一章最值得优先掌握什么?

14.1 先熟练掌握文本读写和 Path

如果你只能先掌握一部分,那优先级通常是:

  • with open(...)
  • Path.read_text() / Path.write_text()
  • Path.glob() / Path.rglob()

因为它们出现频率极高。

14.2 CSV 和 JSON 至少要会基本读写

这两类格式几乎一定会在真实项目中遇到。

  • 表格型数据 → CSV
  • 结构化配置 / 接口数据 → JSON
14.3 批量处理思维比单个 API 更重要

很多人学完会记住很多函数名,但真正缺的是流程感。

你要逐渐形成这样的思路:

  • 找文件;
  • 读数据;
  • 清洗转换;
  • 输出结果;
  • 处理异常。

这比单纯背 read()write() 更有价值。

14.4 多写小脚本,进步最快

最适合练这一章的方式,就是自己给自己设计一些小任务,例如:

  • 清理一个文本文件中的重复行;
  • 统计某个目录下文件数量和大小;
  • 把 CSV 转成 JSON;
  • 批量重命名图片;
  • 合并多个 Markdown 文件。

这些任务不大,但非常锻炼实战能力。


十五、总结

这一篇我们系统梳理了 Python 中“文件读写与数据处理实战”的核心内容:

  1. 文本读取与写入:掌握 open()read()、按行遍历、write() 等基本操作;
  2. pathlib 路径处理:用 Path 更自然地表示和操作文件路径;
  3. 目录遍历:通过 iterdir()glob()rglob() 进行批量文件定位;
  4. 二进制文件处理:理解文本模式与二进制模式的区别;
  5. CSV 处理:使用 csv.readercsv.DictReadercsv.DictWriter 读写表格数据;
  6. JSON 处理:使用 json.load()json.dump() 处理结构化数据;
  7. 数据清洗:学会去空行、去空白、去重、筛选等常见处理思路;
  8. 批量处理:掌握“遍历 → 读取 → 转换 → 输出”的通用自动化流程;
  9. 错误处理:学会在文件不存在、编码错误、权限不足等情况下合理处理异常。

如果说前一篇标准库内容是在介绍“有哪些工具可用”,那么这一篇更像是在回答:

真正拿到文件和数据之后,应该怎样把这些工具组合起来,写成能解决实际问题的脚本?

掌握这一篇之后,你已经能够用 Python 做很多非常实用的自动化任务了。

继续往后写时,比较自然的衔接方向通常有两个:

  • Python网络编程与HTTP请求入门:开始和网络数据、接口打交道;
  • Python常用第三方库入门:例如 requestspandasbeautifulsoup4 等,为更进一步的工程实践做铺垫。

参考资料