文件读写和异常处理
基础教学 1 min read

文件读写和异常处理

Blog Author

文件读写和异常处理:原理、用法与最佳实践教学指南

一、文件系统与数据持久化

概念回顾:

  • 持久化(Persistence):将数据从内存转存到磁盘,常用方式为“写入文件”。
  • 文件系统(File System):负责数据的存储、检索与组织,是操作系统的一部分,为用户隐藏硬盘数据块的细节,提供“文件 + 目录”的操作接口。

教学要点:

  • 使用文件可实现数据持久化,适合保存日志、配置、缓存、静态资源等。
  • 文件系统管理磁盘空间,无需手动分配存储块,程序员只需指定路径与文件名。

二、打开和关闭文件

基础语法:

open(file, mode='r', encoding=None)

常见模式总结:

模式 说明
'r' 只读,文件不存在则异常
'w' 写入,文件存在则清空
'x' 写入,若文件已存在则异常
'a' 追加写入
'b' 二进制模式
't' 文本模式(默认)
'+' 更新模式,读写均可

实践建议:

  • 指定encoding='utf-8'避免跨平台字符集问题。
  • 文件操作后一定要关闭文件,以释放资源。

教学案例:

f = open('example.txt', 'w', encoding='utf-8')
f.write('Hello, Python!')
f.close()

三、读写文本文件

读取方法:

  • read():读取所有内容。
  • readline():读取一行。
  • readlines():按行读成列表。
  • for line in file::逐行读取。

写入方法:

  • write(str):写入字符串。
  • 使用'w''a'模式。

教学示例:

with open('note.txt', 'r', encoding='utf-8') as f:
    for line in f:
        print(line.strip())

最佳实践:

  • 写入前尽量先判断文件是否存在(如使用os.path.exists)。
  • 使用strip()去除换行符。

四、异常处理机制(Exception Handling)

关键词讲解:

关键词 说明
try 尝试执行可能出错的代码块
except 出现异常时执行的代码
else 无异常时执行的代码
finally 无论是否异常都执行的代码(常用于释放资源)
raise 主动抛出异常

教学范例:

try:
    f = open('not_exist.txt', 'r')
except FileNotFoundError:
    print("文件不存在!")
finally:
    print("程序结束")

最佳实践:

  • 不要滥用except捕获所有异常(如:except:),会掩盖Bug。
  • 仅处理你能处理的异常,如:except FileNotFoundError
  • finally中释放文件、网络、数据库等资源。
  • 尽量使用with语法自动处理资源释放。

五、自定义异常与抛出

定义自定义异常:

class MyError(Exception):
    pass

抛出异常:

def check(n):
    if n < 0:
        raise MyError("不能为负数")

教学场景:

  • 参数非法时引发异常。
  • 模块之间传递错误状态。

六、上下文管理器(with语法)

优点:

  • 自动关闭文件,简化代码。
  • 防止忘记调用close()导致资源泄露。

语法示例:

with open('data.txt', 'r', encoding='utf-8') as f:
    data = f.read()

教学建议:

  • 几乎所有文件操作推荐使用with
  • 支持with open(...) as f1, open(...) as f2:的多文件写法。

七、读写二进制文件

区别于文本文件:

  • 模式为 'rb' / 'wb'
  • 操作的是bytes而非str
  • 常用于图片、视频、音频、PDF等非文本数据。

简单复制图片示例:

with open('a.jpg', 'rb') as src, open('b.jpg', 'wb') as dst:
    dst.write(src.read())

分块读写(适合大文件):

with open('bigfile.dat', 'rb') as f1, open('copy.dat', 'wb') as f2:
    chunk = f1.read(1024)
    while chunk:
        f2.write(chunk)
        chunk = f1.read(1024)

教学点:

  • 分块操作可节省内存。
  • 注意避免读取时漏加参数,默认read()可能读取整个文件。

八、综合示例:文件操作 + 异常处理 + 上下文语法

def safe_read(path):
    try:
        with open(path, 'r', encoding='utf-8') as file:
            return file.read()
    except FileNotFoundError:
        return '文件未找到'
    except UnicodeDecodeError:
        return '编码错误'
    except Exception as e:
        return f'发生未知错误:{e}'

教学扩展:

  • 可以引入日志记录模块(如logging)记录异常。
  • 可以使用函数封装读取逻辑,提高重用性。

九、教学总结与最佳实践

推荐做法:

  • with open(...)替代open + close
  • 捕获特定异常类型,避免泛用except:
  • 分离异常处理逻辑与主业务逻辑。
  • 使用文本文件存储结构化数据(如JSON、CSV)时,建议使用标准库支持。
  • 对于大文件使用分块读写方式,避免内存压力。
  • 自定义异常用于标志业务规则违反,而非系统错误。

🚫 避免误区:

  • 不要使用异常控制正常流程(如用try处理文件是否存在)。
  • 不要捕获所有异常再重新抛出同一个异常。
  • 文件读写中不要忽略字符编码的重要性。

如需扩展学习内容(如使用 json 模块进行持久化、临时文件操作、文件权限控制等),可随时继续提问。