一、文件基础
1.1 文件分类
| 类型 | 说明 | 扩展名 |
|---|---|---|
| 纯文本文件 | 人类可读 | .txt、.py、.csv、.json |
| 二进制文件 | 字节流 | .jpg、.mp3、.exe、.pdf |
1.2 文件路径
- 绝对路径:从盘符开始,如
C:\Users\xxx\file.txt - 相对路径:从当前目录开始,如
./data/file.txt
二、文件的打开与关闭
2.1 open() 函数
f = open("test.txt", mode="r", encoding="utf-8") content = f.read() f.close() # 必须关闭!mode 常用值:
| mode | 含义 |
|---|---|
r | 只读(默认) |
w | 写入(覆盖,文件不存在则创建) |
a | 追加(末尾添加) |
rb/wb | 二进制读写 |
2.2 with 语句(强烈推荐!)
with open("test.txt", "r", encoding="utf-8") as f: content = f.read() # 离开 with 块,文件自动关闭,即使发生异常也会关闭三、文件读写
3.1 读取
with open("test.txt", "r", encoding="utf-8") as f: # 一次读全部 content = f.read() # 按行读(返回列表) f.seek(0) lines = f.readlines() # 逐行迭代(推荐,大文件友好) f.seek(0) for line in f: print(line.strip()) # strip 去掉换行符3.2 写入
with open("output.txt", "w", encoding="utf-8") as f: f.write("第一行\n") f.writelines(["第二行\n", "第三行\n"])3.3 追加
with open("log.txt", "a", encoding="utf-8") as f: f.write("新的日志记录\n")3.4 文件拷贝
def copy_file(src, dst): with open(src, "rb") as f_in, open(dst, "wb") as f_out: while True: data = f_in.read(4096) # 每次读 4KB if not data: break f_out.write(data)四、os 模块常用操作
import os print(os.getcwd()) # 当前工作目录 print(os.path.exists("test.txt")) # 文件是否存在 print(os.path.join("dir", "file.txt")) # 拼接路径 os.mkdir("new_dir") # 创建目录 print(os.listdir(".")) # 列出当前目录 # 递归遍历 for root, dirs, files in os.walk("."): for name in files: print(os.path.join(root, name))五、异常处理
5.1 两种错误
| 类型 | 说明 | 例子 |
|---|---|---|
| 语法错误 | 代码不符合 Python 语法 | 忘记冒号、缩进错误 |
| 异常 | 语法正确,运行时报错 | 除零、文件不存在、类型错误 |
5.2 常见异常
| 异常 | 原因 |
|---|---|
ZeroDivisionError | 除以零 |
FileNotFoundError | 文件不存在 |
ValueError | 值不合法,如int("abc") |
TypeError | 类型错误 |
KeyError | 字典键不存在 |
IndexError | 索引越界 |
5.3 try-except-else-finally
try: num = int(input("输入数字:")) result = 10 / num except ValueError: print("输入不是有效数字") except ZeroDivisionError: print("不能除以零") except Exception as e: print(f"未知错误:{e}") else: print(f"结果:{result}") # 无异常时执行 finally: print("无论是否异常都执行")5.4 抛出异常 raise
def set_age(age): if age < 0 or age > 150: raise ValueError(f"年龄 {age} 不合法") return age5.5 assert 断言
def divide(a, b): assert b != 0, "除数不能为零" return a / b5.6 自定义异常
class ScoreError(Exception): """成绩异常""" pass def validate_score(score): if not 0 <= score <= 100: raise ScoreError(f"成绩 {score} 不在 0-100 范围") return score5.7 异常的传递
异常会向上传递,直到被 except 捕获或导致程序崩溃。
六、with 关键字原理
with基于上下文管理器协议(__enter__/__exit__),确保资源释放。
文件对象就是上下文管理器:进入 with 时打开,离开时自动 close。
七、重点易错点
- 读写文件必须指定
encoding="utf-8"(Windows 默认 gbk 易乱码) - 用 with 代替手动 close
- except 顺序:从具体到通用
w模式会覆盖原文件,追加用a
八、练习题
基础题
1.读取文本文件,统计行数、单词数、字符数。
2.将用户输入追加写入diary.txt,每行带时间戳。
3.安全地将字符串转为 int,失败返回 0。
4.用 os.walk 列出当前目录所有 .py 文件。
进阶题
5.实现文件拷贝,支持大文件,捕获 FileNotFoundError。
6.自定义 ScoreError,验证成绩 0~100。
参考答案
点击展开参考答案
from datetime import datetime import os def file_stats(path): with open(path, "r", encoding="utf-8") as f: content = f.read() return len(content.splitlines()), len(content.split()), len(content) def write_diary(text): with open("diary.txt", "a", encoding="utf-8") as f: f.write(f"[{datetime.now()}] {text}\n") def safe_int(s, default=0): try: return int(s) except ValueError: return default class ScoreError(Exception): pass def validate_score(score): if not 0 <= score <= 100: raise ScoreError(f"成绩 {score} 不合法") return score