欢迎来到「Python学习与交流」!在前七课中,我们学会了处理内存中的数据。但你可能已经发现了一个致命问题:程序一关闭,所有数据就消失了。辛辛苦苦录入的通讯录、计算的结果,下次运行又要从头再来。
今天,我们将赋予程序两项至关重要的能力:文件操作让它能把数据永久保存到硬盘,拥有“记忆”;异常处理让它在遇到错误时不会直接崩溃,而是优雅地应对,拥有“韧性”。这两项能力,是区分“玩具代码”和“实用程序”的分水岭。
一、文件读写:让数据持久化
Python 内置了open() 函数,无需安装任何库就能轻松读写文件。它的核心用法遵循一个固定模式:打开 → 操作 → 关闭。
1. 写入文件:保存你的数据
# 'w' 表示写入模式,文件不存在会自动创建,存在则会清空原内容withopen("notes.txt", "w", encoding="utf-8") as f: f.write("第一行笔记\n") f.write("第二行笔记\n")# with 语句块结束后,文件会自动安全关闭,无需手动调用 f.close()
💡 关键提醒:永远使用 with 语句操作文件!它能确保即使代码中途报错,文件也会被正确关闭,避免数据损坏或占用。另外,中文文件务必指定 encoding="utf-8",否则在不同系统上极易出现乱码。2. 读取文件:找回你的记忆
# 'r' 表示只读模式(默认值),文件不存在会报 FileNotFoundErrorwith open("notes.txt", "r", encoding="utf-8") as f: content = f.read() # 一次性读取全部内容 print(content)# 如果文件很大,推荐逐行读取,避免撑爆内存with open("notes.txt", "r", encoding="utf-8") as f: for line in f: print(line.strip()) # strip() 去除每行末尾的换行符
3. 追加模式:不覆盖原有内容
如果你想在文件末尾添加新内容,而不是清空重写,把模式改为 'a'(append)即可:with open("notes.txt", "a", encoding="utf-8") as f: f.write("这是新增的一行\n")
二、异常处理:让程序不再脆弱
现实世界中,文件可能不存在、用户可能输入非法数字、网络可能超时……这些意外被称为“异常”。如果不处理,程序会直接抛出红色错误并终止。try-except 结构就是我们的“安全网”。
1. 基础用法:捕获并处理错误
filename = input("请输入文件名:")try: with open(filename, "r", encoding="utf-8") as f: print(f.read())except FileNotFoundError: print(f"❌ 文件 '{filename}' 不存在,请检查路径")except PermissionError: print("🔒 没有权限读取该文件")
当 try 块中的代码出错时,Python 会立即跳转到匹配的 except块执行,程序不会崩溃。2. 进阶:else 与 finally
- else:仅在 try 块没有发生任何异常时执行,适合放“成功后才做”的逻辑。
- finally:无论是否出错都一定会执行,适合做清理工作(不过用了 with 语句后,文件关闭就不需要它了)。
try: num = int(input("请输入整数:")) result = 100 / numexcept ValueError: print("❌ 输入的不是有效整数")except ZeroDivisionError: print("❌ 除数不能为零")else: print(f"✅ 计算结果:{result}") # 只有没报错才会打印
⚠️ 避坑警告:千万不要写裸 except :(不指定异常类型)!它会吞掉所有错误,包括你根本没预料到的 bug,导致调试极其困难。始终明确指定要捕获的异常类型。三、实战:带持久化的记事本
让我们把文件操作和异常处理结合起来,升级之前的通讯录,让它真正“记住”数据:DATA_FILE = "contacts.txt"def load_contacts(): """从文件加载通讯录""" contacts = {} try: with open(DATA_FILE, "r", encoding="utf-8") as f: for line in f: line = line.strip() if ":" in line: name, phone = line.split(":", 1) contacts[name] = phone except FileNotFoundError: print("📭 首次运行,已创建空通讯录") return contactsdef save_contacts(contacts): """将通讯录保存到文件""" try: with open(DATA_FILE, "w", encoding="utf-8") as f: for name, phone in contacts.items(): f.write(f"{name}:{phone}\n") print("💾 数据已保存") except PermissionError: print("🔒 保存失败:没有写入权限")def main(): contacts = load_contacts() while True: cmd = input("\n命令(add/find/list/quit):").strip().lower() if cmd == "add": name = input("姓名:").strip() phone = input("电话:").strip() contacts[name] = phone save_contacts(contacts) # 每次修改后立即保存 elif cmd == "find": name = input("查找姓名:").strip() phone = contacts.get(name) print(f"📞 {phone}" if phone else f"❌ 未找到 {name}") elif cmd == "list": for name, phone in contacts.items(): print(f" {name}: {phone}") elif cmd == "quit": print("👋 再见!") breakmain()
这个程序实现了完整的数据持久化闭环:启动时从文件加载,修改后自动保存,文件不存在时优雅降级而非崩溃。这才是真正可用的工具。四、新手避坑指南
- 忘记指定编码:Windows 默认 GBK,Mac/Linux 默认 UTF-8,不统一指定encoding="utf-8"必然踩坑。
- 用 'w' 模式误删数据:'w' 会清空文件!想追加内容一定要用 'a',想保留原内容先读再改。
- 裸 except 吞掉所有错误:调试时找不到 bug 的元凶,养成指定具体异常类型的习惯。
- 文件路径含中文或空格:尽量使用相对路径或原始字符串
r"C:\我的文件\data.txt" 避免转义问题。 - 大文件用 read() 一次性读入:几百 MB 的文件会直接撑爆内存,务必改用逐行遍历或
readline()。
五、总结
- with open():安全读写文件的黄金标准,永远优先使用。
- 三种模式:'r' 只读、'w' 写入(清空)、'a' 追加。
- try-except:精准捕获特定异常,让程序优雅应对意外。
至此,Python 基础语法八大核心模块全部收官!你已经掌握了从数据处理到文件持久化、从逻辑控制到错误防御的完整技能树。下一课,我们将进入全新的篇章——模块与包,教你如何使用 Python 庞大的标准库和第三方库,站在巨人的肩膀上构建更强大的应用。