文件读写是 Python 编程中最基础也最重要的能力之一。无论是读取配置文件、处理日志、保存用户数据,还是完成综合应用题中的“数据导入—处理—导出”流程,都离不开文件操作。本报告围绕open(路径, 模式)、read()、readline()、write()、with open() as f:等核心知识点展开,结合完整代码、逐段解析和易错提醒,帮助读者建立清晰、安全、可迁移的文件读写能力。
二、核心概念:open()与文件模式
open()函数用于打开文件,并返回一个文件对象。它的基本语法是:
open(file,mode='r',encoding=None)其中:
file:文件路径,可以是相对路径,也可以是绝对路径;mode:打开模式,决定文件是读取、写入还是追加;encoding:文本编码,处理中文文件时建议显式指定encoding='utf-8'。
常见模式如下:
| 模式 | 含义 | 文件不存在时 |
|---|---|---|
r | 只读 | 报错 |
w | 写入,会清空原内容 | 创建新文件 |
a | 追加写入 | 创建新文件 |
r+ | 读写 | 报错 |
rb/wb | 二进制读写 | 视主模式而定 |
需要特别注意:w模式会清空文件原有内容。如果只是想增加数据,应使用a模式。
三、推荐写法:with open() as f:
打开文件后,如果不关闭文件,可能导致数据没有真正写入磁盘,也可能造成资源泄漏。因此,Python 推荐使用with语句:
withopen("example.txt","r",encoding="utf-8")asf:content=f.read()with语句会在代码块结束后自动关闭文件,即使中间发生异常,也能保证文件被正确关闭。相比手动调用f.close(),这种写法更安全、更简洁。
四、读取文件:read()、readline()、readlines()
1.read():一次性读取全部内容
withopen("data.txt","r",encoding="utf-8")asf:content=f.read()print(content)read()会把整个文件内容读成一个字符串。它适合小文件,但如果文件非常大,一次性读入可能占用较多内存。
2.readline():一次读取一行
withopen("data.txt","r",encoding="utf-8")asf:line=f.readline()whileline:print(line.strip())line=f.readline()readline()每次读取一行,适合逐行处理文件内容。每行末尾通常带有换行符\n,可以使用strip()去除多余空白。
3.readlines():读取所有行并返回列表
withopen("data.txt","r",encoding="utf-8")asf:lines=f.readlines()forlineinlines:print(line.strip())readlines()会把每一行放进一个列表中。这种方式方便后续按索引访问,但同样不适合超大文件。
4. 更推荐的逐行遍历方式
withopen("data.txt","r",encoding="utf-8")asf:forlineinf:print(line.strip())直接遍历文件对象可以逐行读取,内存占用较低,是处理较大文本文件时的常用写法。
五、写入文件:write()与writelines()
写入文件时要注意模式选择。w会覆盖原内容,a会在文件末尾追加。
# 覆盖写入withopen("output.txt","w",encoding="utf-8")asf:f.write("姓名,成绩\n")f.write("张三,92\n")f.write("李四,87\n")# 追加写入withopen("output.txt","a",encoding="utf-8")asf:f.write("王五,95\n")write()只能写入字符串。如果要写入数字,需要先转换为字符串,例如str(95)。writelines()可以写入一个字符串列表,但它不会自动添加换行符,需要手动保证每行包含\n。
六、综合示例:学生成绩处理系统
下面给出一个较为完整的综合应用示例,包含读取、处理、写入和异常处理。
importos INPUT_FILE="scores.txt"OUTPUT_FILE="report.txt"defread_scores(path):"""读取学生成绩文件,返回列表"""scores=[]try:withopen(path,"r",encoding="utf-8")asf:forlineinf:line=line.strip()ifnotline:continueparts=line.split(",")iflen(parts)!=2:continuename=parts[0].strip()try:score=float(parts[1].strip())exceptValueError:continuescores.append((name,score))exceptFileNotFoundError:print(f"文件{path}不存在,请先创建成绩文件。")exceptPermissionError:print(f"没有权限读取文件:{path}")returnscoresdefanalyze(scores):"""计算最高分、最低分、平均分和及格率"""ifnotscores:returnNonevalues=[sfor_,sinscores]highest=max(values)lowest=min(values)average=sum(values)/len(values)passed=sum(1forvinvaluesifv>=60)pass_rate=passed/len(values)*100return{"人数":len(values),"最高分":highest,"最低分":lowest,"平均分":round(average,2),"及格率":f"{pass_rate:.2f}%"}defwrite_report(path,scores,result):"""写入统计报告"""withopen(path,"w",encoding="utf-8")asf:f.write("学生成绩统计报告\n")f.write("="*20+"\n")forname,scoreinscores:f.write(f"{name}:{score}\n")f.write("\n统计结果:\n")forkey,valueinresult.items():f.write(f"{key}:{value}\n")print(f"报告已保存到{path}")defmain():# 1. 准备示例数据ifnotos.path.exists(INPUT_FILE):withopen(INPUT_FILE,"w",encoding="utf-8")asf:f.write("张三,88\n")f.write("李四,72\n")f.write("王五,95\n")f.write("赵六,59\n")f.write("孙七,63\n")# 2. 读取数据scores=read_scores(INPUT_FILE)# 3. 分析数据result=analyze(scores)ifresultisNone:print("没有可分析的成绩数据。")return# 4. 输出结果forkey,valueinresult.items():print(f"{key}:{value}")# 5. 写入报告write_report(OUTPUT_FILE,scores,result)if__name__=="__main__":main()七、代码解析
- 读取阶段:
read_scores()使用for line in f逐行读取,避免一次性加载大文件。每行通过split(",")拆分,并用try...except处理成绩转换失败的情况。 - 分析阶段:
analyze()负责计算最高分、最低分、平均分和及格率。这里把数据读取和数据分析分开,结构更清晰。 - 写入阶段:
write_report()使用w模式生成报告文件。由于报告需要重新生成,所以使用覆盖写入是合理的。 - 主流程:
main()先判断文件是否存在,不存在则创建示例数据,再依次完成读取、分析、输出和保存。 - 异常处理:程序捕获了
FileNotFoundError、PermissionError和ValueError,避免因为文件缺失或数据格式错误导致程序直接崩溃。
八、报告亮点
1. 始终使用with管理文件
所有文件操作都放在with块中,确保文件使用结束后自动关闭,避免资源泄漏。
2. 显式指定encoding='utf-8'
中文环境下,文件读写容易出现乱码。显式指定utf-8编码可以显著提高程序在不同系统中的稳定性。
3. 区分w和a的使用场景
示例中创建示例数据时使用w,因为需要生成新文件;追加日志或新增记录时则应使用a,防止误删原有内容。
4. 大文件友好的读取方式
程序没有使用readlines()一次性读入所有行,而是通过for line in f逐行处理。这在处理日志、成绩单、交易记录等较大文本文件时更安全。
5. 异常处理完善
程序针对文件不存在、权限不足、数据格式错误分别做了处理,使程序更加健壮。这也是综合应用题中容易加分的写法。
6. 结构化设计
读取、分析、写入分别封装成函数,主函数只负责流程控制。这样的结构便于测试、修改和复用。
九、常见易错点
- 忘记指定编码:处理中文文本时容易乱码,应写
encoding='utf-8'。 - 误用
w模式:w会清空文件内容,追加数据应使用a。 - 忘记关闭文件:手动
open()后必须close(),推荐使用with。 - 大文件使用
read()或readlines():可能导致内存占用过高,应优先逐行迭代。 - 写入数字未转字符串:
write()只能写入字符串,数字需要先str()转换。 - 路径写法不兼容:跨平台路径建议使用
os.path.join()或pathlib.Path。
十、总结
Python 文件读写并不只是记住open()、read()、write()几个函数,更重要的是理解模式选择、资源管理、编码处理和异常保护。实际开发中,with open() as f:几乎应成为默认写法;处理中文文件时要显式指定encoding='utf-8';面对大文件要优先逐行读取;面对不确定输入时要加入异常处理。掌握这些要点后,无论是完成课程实验、处理日志数据,还是应对综合应用题,都能写出更稳定、更规范的 Python 程序。