news 2026/5/28 2:41:08

12 - 文件操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
12 - 文件操作

12 - 文件操作

跟文件打交道是写程序绕不开的事。读配置、写日志、处理数据… 这章把 Python 的文件操作讲清楚。


读写文本文件

写文件

# 写入文件(覆盖原有内容)withopen("hello.txt","w",encoding="utf-8")asf:f.write("你好,世界\n")f.write("第二行\n")

几个要点:

  • "w"是写入模式(write),会覆盖已有内容
  • encoding="utf-8"指定编码,防止中文乱码。强烈建议每次都写这个
  • with语句会自动帮你关闭文件,不用手动f.close()

读文件

# 读取整个文件withopen("hello.txt","r",encoding="utf-8")asf:content=f.read()print(content)# 按行读取(更省内存,大文件推荐)withopen("hello.txt","r",encoding="utf-8")asf:forlineinf:print(line.strip())# strip() 去掉行尾的换行符# 读取所有行到列表withopen("hello.txt","r",encoding="utf-8")asf:lines=f.readlines()print(lines)# ['你好,世界\n', '第二行\n']

追加写入

# "a" 是追加模式(append),不会覆盖原有内容withopen("hello.txt","a",encoding="utf-8")asf:f.write("这是追加的内容\n")

打开模式一览

模式说明
"r"读取(默认),文件不存在会报错
"w"写入,文件不存在会创建,存在会覆盖
"a"追加,文件不存在会创建
"x"创建,文件已存在会报错
"b"二进制模式(跟上面组合,如"rb""wb"
"+"读写模式(如"r+"

with 语句的重要性

你可能会看到有人这样写:

f=open("hello.txt","r")content=f.read()f.close()

这能用,但有个问题:如果f.read()出了异常,f.close()就不会被执行,文件就一直开着。虽然 Python 退出时会自动关闭,但这不是好习惯。

with语句(上下文管理器)保证不管发生什么,文件最终都会被关闭:

withopen("hello.txt","r")asf:content=f.read()# 不管这里有没有异常,f 都会被关闭

永远用with操作文件,别犹豫。


路径处理

用 pathlib(推荐)

Python 3.4 引入的pathlib模块,比老式的os.path好用太多了:

frompathlibimportPath# 创建路径对象p=Path("data/output/result.txt")# 常用属性print(p.name)# result.txt(文件名)print(p.stem)# result(文件名不含后缀)print(p.suffix)# .txt(后缀)print(p.parent)# data/output(父目录)print(p.parts)# ('data', 'output', 'result.txt')# 拼接路径(用 / 运算符,非常直观)base=Path("data")output=base/"output"/"result.txt"print(output)# data/output/result.txt

文件是否存在

p=Path("hello.txt")print(p.exists())# True/Falseprint(p.is_file())# 是不是文件print(p.is_dir())# 是不是目录

创建目录

# 创建目录(父目录不存在会自动创建)Path("data/output").mkdir(parents=True,exist_ok=True)

遍历目录

# 列出当前目录下的所有文件forfinPath(".").iterdir():print(f)# 用 glob 模式匹配forfinPath(".").glob("*.py"):print(f)# 递归查找forfinPath(".").rglob("*.py"):print(f)

读取和写入(pathlib 的简写)

p=Path("hello.txt")# 一行读取content=p.read_text(encoding="utf-8")# 一行写入p.write_text("你好",encoding="utf-8")# 二进制读写data=p.read_bytes()p.write_bytes(b"\x00\x01\x02")

小文件用这种写法特别方便,省了 with 语句。大文件还是老老实实用open()逐行读。


处理 CSV 文件

CSV 就是逗号分隔的文本文件,Excel 能打开那种。

用标准库的 csv 模块

importcsv# 写 CSVwithopen("data.csv","w",newline="",encoding="utf-8")asf:writer=csv.writer(f)writer.writerow(["姓名","年龄","城市"])# 写表头writer.writerow(["小明",25,"北京"])writer.writerow(["小红",22,"上海"])# 读 CSVwithopen("data.csv","r",encoding="utf-8")asf:reader=csv.reader(f)header=next(reader)# 跳过表头forrowinreader:print(f"{row[0]},{row[1]}岁,{row[2]}")# 用 DictReader 更方便(直接用列名访问)withopen("data.csv","r",encoding="utf-8")asf:reader=csv.DictReader(f)forrowinreader:print(f"{row['姓名']},{row['年龄']}岁")

newline=""是为了防止 Windows 下出现空行。

用 pandas(更强大)

如果数据量大或者需要复杂操作,pandas 更合适:

# 先安装# uv add pandasimportpandasaspd# 读df=pd.read_csv("data.csv")print(df)# 写df.to_csv("output.csv",index=False)

处理 JSON 文件

JSON 是最常用的数据交换格式,跟 Python 字典长得很像。

importjson# Python 字典转 JSON 字符串data={"name":"小明","age":25,"hobbies":["读书","游泳"]}# 转为 JSON 字符串json_str=json.dumps(data,ensure_ascii=False,indent=2)print(json_str)# JSON 字符串转 Python 字典parsed=json.loads(json_str)print(parsed["name"])# 小明# 写入文件withopen("data.json","w",encoding="utf-8")asf:json.dump(data,f,ensure_ascii=False,indent=2)# 从文件读取withopen("data.json","r",encoding="utf-8")asf:data=json.load(f)

注意ensure_ascii=False,不加的话中文会被转成\uXXXX形式。indent=2让输出有缩进,好看一些。

JSON 和 Python 的类型对应

PythonJSON
dictobject{}
list/tuplearray[]
strstring""
int/floatnumber
True/Falsetrue/false
Nonenull

处理二进制文件

图片、音频、视频这些不是文本,需要用二进制模式:

# 复制文件withopen("photo.jpg","rb")assrc:data=src.read()withopen("photo_copy.jpg","wb")asdst:dst.write(data)# 也可以用 shutil 一行搞定importshutil shutil.copy2("photo.jpg","photo_copy.jpg")

文件操作的常见模式

读取配置文件

importjsonfrompathlibimportPathdefload_config(path="config.json"):p=Path(path)ifp.exists():returnjson.loads(p.read_text(encoding="utf-8"))return{}# 文件不存在返回空配置defsave_config(config,path="config.json"):Path(path).write_text(json.dumps(config,ensure_ascii=False,indent=2),encoding="utf-8")

日志记录

fromdatetimeimportdatetimefrompathlibimportPathdeflog(message,logfile="app.log"):timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")withopen(logfile,"a",encoding="utf-8")asf:f.write(f"[{timestamp}]{message}\n")log("程序启动")log("用户登录")log("程序结束")

当然实际项目中会用logging标准库,比手写方便得多:

importlogging logging.basicConfig(filename="app.log",level=logging.INFO,format="%(asctime)s %(levelname)s %(message)s")logging.info("程序启动")logging.warning("内存不足")logging.error("数据库连接失败")

本章小结

  • with open()操作文件,自动管理资源
  • 读写时记得指定encoding="utf-8"
  • pathlib是现代 Python 处理路径的首选方式
  • CSV 用csv模块,JSON 用json模块
  • 小文件可以一次读完,大文件用逐行读取
  • logging模块比手写日志文件方便得多

面试题

Q1:为什么推荐用with语句操作文件?

点击查看答案

with语句(上下文管理器)保证文件在使用完毕后自动关闭,即使中间发生异常也不例外。

不用with的话,如果读取过程中出错,close()不会被执行,可能导致文件句柄泄漏。用try/finally也能解决但代码更啰嗦。

with不仅用于文件,任何需要"用完清理"的资源(数据库连接、锁等)都适合用上下文管理器。

Q2:读取大文件时应该怎么做?为什么不能直接用f.read()

点击查看答案

f.read()会一次性把整个文件读进内存。如果文件很大(比如几个 GB),会导致内存不足或程序变慢。

正确的做法是逐行读取:

withopen("big_file.txt")asf:forlineinf:process(line)

for line in f是惰性读取,每次只在内存中保留一行。无论文件多大,内存占用都很小。

Q3:json.dumps()ensure_ascii=False的作用是什么?

点击查看答案

默认情况下json.dumps()会把非 ASCII 字符(如中文)转成\uXXXX形式:

json.dumps({"name":"小明"})# '{"name": "\\u5c0f\\u660e"}'

设置ensure_ascii=False后,会保留原始字符:

json.dumps({"name":"小明"},ensure_ascii=False)# '{"name": "小明"}'

在处理中文数据时通常需要设置这个参数,否则输出的 JSON 不可读。

Q4:pathlib相比os.path有什么优势?

点击查看答案
  1. 面向对象pathlib用 Path 对象代替字符串,有丰富的方法和属性
  2. 路径拼接直观:用/运算符代替os.path.join()
  3. 跨平台:自动处理不同系统的路径分隔符
  4. 功能集成:读写文件、遍历目录等操作都集成在 Path 对象上
  5. 链式调用Path("data").joinpath("output").with_suffix(".json")

os.path也能做到所有事情,但代码更冗长。新项目推荐用pathlib


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 2:40:23

终极指南:如何在Obsidian中创建和嵌入专业Excel表格

终极指南:如何在Obsidian中创建和嵌入专业Excel表格 【免费下载链接】obsidian-excel 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-excel 还在为Obsidian中处理表格数据而烦恼吗?Obsidian Excel插件让你在笔记应用中直接创建、编辑和…

作者头像 李华
网站建设 2026/5/28 2:39:12

车规 EMC 设计全流程指南:从原理图到量产的实战避坑手册

摘要:车规级 EMC(电磁兼容)是汽车电子量产的核心门槛,直接决定产品的安全性与可靠性。不同于消费电子,车载场景面临宽温波动、高压抛负载、强电磁耦合等极端工况,80% 的 EMC 问题源于前端设计疏漏&#xff…

作者头像 李华
网站建设 2026/5/28 2:39:12

PLC故障解析与抗干扰策略详解

PLC系统于工业现场运行之际, 常常会因外部干扰致使程序跑飞, 还会造成数据错误, 甚至出现硬件损坏的情况。好多人一旦碰到PLC出现问题, 就会怀疑是硬件质量的缘故, 实际上大部分故障的根源在于电磁干扰, 或者是接地不良, 又或者是布线混乱。能够掌握故障解析方法以及抗干扰策略…

作者头像 李华
网站建设 2026/5/28 2:39:10

React技术周刊 2026年第17周

阅读原文: https://mp.weixin.qq.com/s/G6dWSO84Xes1oPwuMymKnA 本周React生态重磅更新:Rspack 2.0实验性支持RSC,TypeScript 7.0 Beta以Go驱动实现10倍编译提速,Expo获4500万美元B轮融资并引入Meta前React负责人,React Compiler渲…

作者头像 李华