尧图精选

Python文件处理入门:从读写到CSV/JSON的实用指南

🕒 发布时间:2026/9/28 9:05:18 📁 来源:尧图网络
1. 为什么Python入门第一道坎我建议放在文件处理上很多零基础的朋友学Python前两周还在跟着教程打印“Hello World”、算个九九乘法表到了第三周突然发现教程开始让你写爬虫、做数据分析结果第一步就卡在“怎么把数据存下来”“怎么读别人给的文件”上。这时候才回头补文件处理节奏就乱了。我自己的体会是文件处理是Python入门阶段性价比最高的一块内容。它不需要你懂网络、不用装数据库一个.txt文件加自带的标准库就能跑通但它几乎串联了后面所有方向的基础爬虫要保存网页、数据分析要读CSV和Excel、自动化办公要批量改文件名、量化策略要把历史行情落盘。如果你在入门阶段把文件读写练熟了后面学任何方向都会顺畅很多。这篇文章我按自己带新人的经验来写不讲大而全的理论直接给你一条从零到能干活的操作路径。从路径、编码这些新手最容易踩坑的概念讲起到文本文件怎么读怎么写再到CSV和JSON这两类日常最常用的格式怎么处理最后加一批真实场景里的文件管理脚本和踩坑经验。每段代码都是可以直接复制运行验证的运行环境是普通Windows或macOS上的Python 3.8以上版本。顺便说一句很多新手问到底要不要先学完“所有基础语法”再来搞文件处理我的答案是不需要。你只需要知道变量、if判断、for循环、函数定义这四件事文件处理这部分就能练起来。边做边补语法学得反而快。2. 动手读文件前必须先搞懂的三件小事2.1 路径相对路径和绝对路径到底用哪个读文件的第一步不是写代码是找对文件的“地址”。路径这事儿看起来简单但新手经常在这里耗掉一晚上。绝对路径很好理解就是文件在电脑里的完整位置。Windows上长这样C:\Users\你的用户名\Desktop\test.txtmacOS和Linux上长这样/Users/你的用户名/Desktop/test.txt。用绝对路径写代码最稳不管你的程序从哪个目录启动都能找到文件但缺点是不够灵活换台电脑或者改了目录结构就要改代码。相对路径是相对于“当前工作目录”的路径。新手最容易懵的地方就在这里当你双击运行一个.py脚本当前工作目录不一定是脚本所在的目录。比如你在PyCharm里运行脚本当前工作目录通常是项目根目录在终端里输入python xxx.py运行时当前工作目录是你敲命令时所在的那个目录。很多新手明明把文件放在脚本旁边代码里写open(data.txt)却报“文件不存在”一查发现是工作目录不对。我的建议是入门阶段写练习代码直接用绝对路径省脑子等开始做真实项目再用相对路径配pathlib来处理。pathlib是Python 3.4以后官方推荐的路径处理库后面我会专门说到。2.2 编码中文乱码的根源就是它编码这关躲不过去因为你只要用Python读过中文文本几乎都会碰上乱码问题。一句话讲清楚编码的本质计算机只认字节我们看的汉字和字母都是人为规定的映射表。同一段中文用UTF-8编码是一串字节用GBK编码是另一串字节。你读写文件时用的编码和文件本身的编码不一致出来的就是乱码。Python 3的open()函数默认编码是utf-8在macOS和Linux上这基本没问题但在Windows上有个大坑很多Windows原生的文本文件是用GBK代码页936编码保存的尤其是你用“记事本”保存的txt、从老系统导出的数据文件、别人从Excel复制粘贴保存的文本。你用默认的UTF-8编码去读轻则出现乱码重则直接抛UnicodeDecodeError异常。解决思路很简单读写文件时显式指定编码不要依赖默认值。读不确定编码的文件可以先用chardet之类的库检测一下但那是进阶操作。入门阶段你只需要记住自己写文件用UTF-8读取来源不明的文件先试试UTF-8报错了再换GBK试。2.3 open()函数的模式参数r、w、a到底怎么选open()函数是文件操作的入口签名是open(file, mode)这个mode参数新手经常搞混。我直接给你一个速查表模式含义文件不存在时写内容的位置常用场景r只读报错不可写读取已有文件w只写自动创建覆盖从头写重新生成文件a追加写自动创建写到末尾日志记录r读写报错从开头写需要修改原文件w读写自动创建覆盖从头写同时读写新文件a读写自动创建从末尾写边读边追加新手使用中实际会发生的一个意外是w模式会把原文件内容直接清空。很多人本意是想在文件后面加一行结果用了w跑一遍代码之前的数据全没了而且没有“撤销”这一说。所以只要不是存心要覆盖文件一律用a或者先读后写。3. 文本文件读写实操三种读取方式和两种写入流3.1 read()、readline()、readlines()的区别与选择读文本文件核心API就是read家族三种方法各有适用场景。我分别写一下# 写法一一次全部读入为一个字符串 with open(demo.txt, r, encodingutf-8) as f: content f.read() print(len(content)) # 返回整个文件字符数 # 写法二一次读一行 with open(demo.txt, r, encodingutf-8) as f: line f.readline() print(line) # 只读第一行 # 写法三全部读入为一个字符串列表每行是一个元素 with open(demo.txt, r, encodingutf-8) as f: lines f.readlines() print(len(lines)) # 返回文件行数三个写法的选择标准其实很明确文件小比如几兆以内、做一次性分析时用read()或者readlines()都行代码简洁文件很大比如几百兆的日志文件时千万别用这两种否则内存直接撑爆这时候用for line in f逐行迭代这是第四种读法也是大文件处理的推荐做法with open(big_log.txt, r, encodingutf-8) as f: for line in f: # 处理每一行 if ERROR in line: print(line.strip())注意我上面每段代码都用了with open(...) as f:这种写法。这叫上下文管理器它的好处是不管代码块里发生什么情况哪怕抛异常文件都会被自动关闭。新手最容易犯的错就是到处用f open(...)读文件读完忘了f.close()。文件没关掉的后果在Windows上尤其明显程序没结束前文件被占用你手动去删都删不掉。所以我统一建议一律用with语句永远不用担心关闭问题。readline()单独使用频率其实不高它更多出现在循环逻辑里。有一个细节提醒readline()读回来的行末尾带着换行符\n直接print会看到多一个空行配合line.strip()或者line.rstrip(\n)去掉即可。3.2 写入文件的两种方式覆盖写和追加写写入用的API是write()和writelines()。我直接上一个最常见的场景把列表里的多行文本写入文件。lines [第一行内容, 第二行内容, 第三行内容] # 覆盖写入每次运行都会清空重建 with open(output.txt, w, encodingutf-8) as f: for line in lines: f.write(line \n) # write不会自动加换行符必须自己加 # 追加写入在文件末尾增加内容 with open(output.txt, a, encodingutf-8) as f: f.write(追加的这一行\n)write()不会自动帮你在字符串末尾加换行符这是新手写完后打开文件发现所有内容挤在一行的最常见原因。解决方式就是像我上面那样手动拼上\n。如果你要写的内容本来就放在一个列表里也可以用writelines([第一行\n, 第二行\n])注意它也不会自动加换行列表里的每个元素得自己带好换行符。还有一个容易忽略的点写入时编码同样要显式指定。如果你用open(output.txt, w)而不指定encoding在Windows下会用默认的GBK编码写入这个文件拿到别的电脑、或者交给爬虫、数据分析场景去读很容易出现兼容性问题。所以统一用encodingutf-8写是对自己和别人都负责的做法。3.3 一个综合小例子读取→处理→写出光会读和写还不行得能串起来用。我写一个入门阶段最经典的例子从源文件读取多行商品价格文本过滤掉价格超过100的商品把结果写入新文件。def filter_expensive_goods(src_file, dst_file, price_limit100): with open(src_file, r, encodingutf-8) as f: lines f.readlines() filtered [] for line in lines: # 假设每行格式商品名,价格 line line.strip() if not line: continue name, price_str line.split(,) price float(price_str) if price price_limit: filtered.append(f{name},{price}\n) with open(dst_file, w, encodingutf-8) as f: f.writelines(filtered) if __name__ __main__: filter_expensive_goods(goods.txt, goods_filtered.txt)这个脚本思路完全能延伸到很多场景日志里筛出ERROR行、聊天记录里筛出关键词、账单里汇总金额。你可以先在命令行里跑一遍观察goods_filtered.txt的生成情况和内容。这就是“读-处理-写”三段式的标准范式。4. 日常最常用的两类文件格式CSV和JSON4.1 CSV用csv模块不要自己split到了真实项目里文本文件多数不是随便的txt而是有结构的格式。CSV是其中最常见的一种Excel能直接打开各种系统导出数据也常用它。很多新手图省事用split(,)来解析CSV这是个大坑。CSV的字段里如果包含逗号、换行、引号split就会解析错误。正确做法是用Python标准库的csv模块。import csv # 读取CSV with open(students.csv, r, encodingutf-8) as f: reader csv.reader(f) header next(reader) # 跳过表头 for row in reader: print(row) # row是一个列表每个元素对应一列 # 写入CSV with open(students_out.csv, w, encodingutf-8, newline) as f: writer csv.writer(f) writer.writerow([姓名, 语文, 数学]) # 写表头 writer.writerow([张三, 88, 92]) writer.writerow([李四, 75, 85])这里有个连老手都会偶尔踩的细节写CSV文件时必须加上newline参数。如果不加在Windows上写完的CSV每行之间会多一个空行因为系统的换行符和CSV模块内部的换行逻辑冲突了。这个问题排查起来挺隐蔽的我先给你打个预防针。如果数据量小而且你想直接拿列名访问数据可以更省事用csv.DictReader和csv.DictWriter读出来的每一行是字典键就是表头。import csv with open(students.csv, r, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: print(row[姓名], row[数学])4.2 JSONPython字典的“亲兄弟”JSON是现在程序间交换数据最通用的格式爬虫接口返回的数据、配置文件、网络请求体基本全是JSON。Python处理JSON极其顺手原因很简单JSON的对象和数组天生就对应Python的字典和列表。import json # 读取JSON文件 with open(config.json, r, encodingutf-8) as f: data json.load(f) print(data[name]) print(data[items][0][title]) # 把Python对象写入JSON文件 config { name: 我的爬虫, version: 1.0, items: [ {title: Python入门, price: 19.9}, {title: 文件处理, price: 29.9} ] } with open(config_out.json, w, encodingutf-8) as f: json.dump(config, f, ensure_asciiFalse, indent2)注意到写入那里的两个参数了没有ensure_asciiFalse非常关键。如果不加JSON里的中文会被转成\u6211\u7684这种Unicode转义序列文件打开看着跟天书一样虽然程序读起来没问题但人眼排查数据就痛苦了。indent2是让输出内容缩进两个空格文件会变得层级清晰方便调试时人工查看。还有一个常被问到的问题json.load读文件json.loads读字符串两者别搞混。从网络接口拿到的是字符串用loads从文件里读直接用load。记住这个就能少报一个AttributeError。4.3 大文件处理思路不要一次load进来JSON和CSV都有“文件特别大”的场景。CSV还好可以用前面说的for row in reader逐行迭代JSON就比较尴尬因为json.load会把整个文件解析成一个Python对象放内存里几百兆的JSON直接内存溢出。真正生产环境里处理超大JSON文件要用ijson这类流式解析库一行一行地读取JSON结构但那属于进阶话题入门阶段你只需要建立这个意识遇到大文件第一反应应该是“能不能逐行处理”而不是一把梭全读进内存。批量处理100个小的JSON文件也远好过硬扛1个1GB的JSON文件。5. 实战中的文件管理遍历目录、批量改名、安全删除5.1 用pathlib替代os.path路径操作更省心文件处理不只是读写文件内容还包括对文件本身的管理查找、改名、复制、删除、遍历目录。Python老教程里这些都是os.path的活但Python 3.6以后我强烈推荐直接用pathlib它的API设计更直观代码读起来像在说人话。from pathlib import Path # 拼接路径不要再手动用字符串拼了 data_dir Path(data) / 2025 / logs print(data_dir) # data/2025/logs # 判断文件和目录是否存在 p Path(test.txt) print(p.exists(), p.is_file(), p.is_dir()) # 列出目录下所有txt文件 for f in Path(data).glob(*.txt): print(f.name, f.stat().st_size) # 递归列出所有py文件 for f in Path(project).rglob(*.py): print(f)Path对象的/运算符用来拼接路径这在Windows和macOS上都能正确处理分隔符问题你再也不用操心Windows的\和Linux的/了。glob(*.txt)是查找当前目录下的文件rglob(*.py)是递归查找所有子目录这两个方法写自动化脚本时使用极多。5.2 批量重命名脚本一次搞定上百个文件批量重命名是我做过最多的“小工具”类需求。比如给一堆图片加上日期前缀或者把日志文件按序号重排。下面这个脚本做的事情是把当前目录下所有*.txt文件重命名为file_1.txt、file_2.txt这样的格式。from pathlib import Path def batch_rename(pattern*.txt, prefixfile): data_dir Path(.) # 当前目录 counter 1 for f in sorted(data_dir.glob(pattern)): new_name Path(f.parent, f{prefix}_{counter}{f.suffix}) f.rename(new_name) print(f{f.name} - {new_name.name}) counter 1 if __name__ __main__: batch_rename()这里有几个细节值得说。f.suffix取得文件扩展名这样你只改名字主体、不碰后缀。f.parent保留原目录避免把文件移动到意外位置。sorted()保证重命名顺序是确定性的不然系统返回文件的顺序可能乱掉脚本跑完你都不知道哪个文件叫什么了。5.3 文件存在性检查和删除操作的安全意识删除文件是危险操作脚本里必须要做防呆处理。Python删除文件用Path.unlink()但删之前一定要判断存在性否则会抛FileNotFoundError。from pathlib import Path def safe_delete(path_str): p Path(path_str) if not p.exists(): print(f文件不存在: {path_str}) return # 二次确认防止误删 answer input(f确认删除 {p.name} ? (y/n): ) if answer.lower() y: p.unlink() print(已删除) else: print(取消删除)如果你在写自动化脚本没法交互式确认我建议的做法是先移动到回收站而不是直接删除。Windows上可以用send2trash这个第三方库一句send2trash.send2trash(str(f))就把文件送进回收站万一误删还能救回来。这个库我在处理批量清理文件时几乎必用。另外Path对象还有个p.with_suffix(.txt)方法用来替换文件扩展名以及p.stem取文件名不带后缀。这些零碎API不用全背用到时查一下就好但知道它们存在能帮你少写很多麻烦代码。6. 我踩过的那些坑编码、路径、权限与文件占用6.1 编码坑Windows的GBK默认值带来的一系列事故这是我带新人时见过最多的问题没有之一。举一个具体场景你在Windows上写了一个Python脚本用open(data.txt, r)读一个UTF-8编码的文件脚本运行后直接抛错UnicodeDecodeError: gbk codec cant decode byte 0x9a in position 8: illegal multibyte sequence报错信息里出现gbk就是Windows默认编码在作祟。解决办法如前面所说读取时显式加encodingutf-8。反过来还有一种情况你在macOS上用UTF-8读了别人从Windows发来的GBK文件乱码成“锟斤拷”一类的东西那就是你用了UTF-8去解码GBK的内容。除了读写时指定编码还有一个容易被忽略的地方input()和print()在Windows控制台里的编码也可能出问题但那通常只影响乱码显示不影像数据本身等学到爬虫再一并处理也不迟。入门阶段你就记着一个原则打开任何文本文件都显式说清楚编码——我不知道别人会用哪个平台跑你的代码但只要保持这种习惯至少你自己这边的活儿会稳很多。6.2 路径坑反斜杠、转义字符、中文路径Windows路径里的反斜杠\在Python字符串里是转义字符这就是为什么新手写open(C:\Users\test.txt)时会莫名报错。比如\t会被当成制表符\U会被当成Unicode前缀。旧式写法会用双反斜杠绕开C:\\Users\\test.txt但更推荐用原始字符串rC:\Users\test.txt或者直接用Path(C:/Users/test.txt)——pathlib连正反斜杠都帮你处理了。中文路径在绝大多数情况下是能正常工作的但某些老库或压缩包处理场景下会出编码问题。我的建议是自己建项目、建目录时尽量用英文命名这不只是Python的问题也能避免以后部署到Linux服务器上时出现各种诡异的乱码路径问题。6.3 权限坑文件被占用和PermissionErrorWindows上最常见的权限问题不是“没权限读”而是“文件被占用”。你在脚本里写入完成没有关闭文件或者打开文件的程序还没退出比如用Excel打开了那个CSV这时候再去移动或删除文件就会报PermissionError: [WinError 32] 另一个程序正在使用此文件进程无法访问。这就是我前面反复强调with语句的原因——它保证文件用完即关。如果已经遇到这个报错先检查代码里是否有忘了close()的open()调用再看是否有Excel、记事本之类的程序正开着目标文件。把占用文件的外部程序关掉问题通常就解决了。还有一种权限问题发生在试图写入只读文件、或者写入受系统保护的位置比如C:\Program Files。入门阶段的脚本一般不会碰到如果碰到了检查文件属性去掉只读勾选或者把输出路径改到你有完全控制权限的用户目录下比如桌面和文档。6.4 一个综合练习日志文件的按天归档上面讲了一堆零散的经验最后我安排一个能串联所有知识点的综合练习把一个大日志文件按日期拆分出来每天的内容单独存一个文件。这个技能在很多真实工作场景里都有用到。from pathlib import Path def split_log_by_date(log_path): log_file Path(log_path) if not log_file.exists(): print(日志文件不存在) return with open(log_file, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue # 假设每行开头是YYYY-MM-DD格式例如 2025-03-16 10:00:00 INFO ... date_str line[:10] out_path Path(flogs_by_date/{date_str}.log) out_path.parent.mkdir(parentsTrue, exist_okTrue) with open(out_path, a, encodingutf-8) as out_f: out_f.write(line \n) if __name__ __main__: split_log_by_date(app.log)这里的核心逻辑你已经学过了for line in f逐行迭代、切片取日期、mkdir(parentsTrue, exist_okTrue)自动创建目录、追加模式写入。如果日志量特别大还可以加一个缓存字典按日期先收集行列表最后一次性写文件减少频繁打开文件的性能开销这个留给有兴趣的读者自己改进。我在实际项目里还遇到过日志时间戳不止日期一种格式、日志行跨多行、编码不一等复杂情况那时就需要用正则和更精细的分词逻辑了。但不管多复杂的场景底层还是今天讲的这套“读一行→处理→写一行”的模式。把基础打牢复杂情况只是在这个框架上加判断逻辑而已。7. 给初学者的最后几个建议文件处理这块内容我经常跟新人说光看教程不如动手写脚本。哪怕你只是把自己电脑上某个文件夹里的文件按大小排个序、把手机相册导出文件的文件名批量规范一下、把每周的支出记录存成一个CSV这些小事用Python跑一遍比刷十遍语法书管用得多。开发环境方面入门阶段随便用一个趁手的文本编辑器或者VS Code都行。安装Python时记得勾选“Add Python to PATH”这个坑每位新手几乎都会遇到装完Python在终端里输python却提示“不是内部或外部命令”十有八九就是没勾这个选项。最后分享一下我自己写文件处理脚本时的一个习惯永远给编码加上参数永远用with打开文件永远在删除文件前做检查。这三点看着简单但每一条背后都有无数个新手包括当年的我用实际报错换来的教训。把这三条变成肌肉记忆后你在文件处理这一块基本就算出师了。接下来可以放心往数据解析、爬虫、自动化办公这些方向走因为文件读写作为基本功你已经真正过关了。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →