03-文件操作与异常处理

judgingly
6
2026-02-14

Python 学习教程 - 第三篇:文件操作与异常处理

欢迎回到 Python 学习之旅!今天我们将学习如何处理文件和如何优雅地处理错误。

目录

  1. 文件操作基础
  2. 文件读写
  3. 异常处理
  4. 模块与包
  5. 综合练习
  6. 总结

文件操作基础

文件操作是编程中非常重要的技能,让我们能够处理数据持久化。

文件路径

import os

# 相对路径
file_path = "data.txt"

# 绝对路径
abs_path = "/home/user/data.txt"

# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前目录:{current_dir}")

# 获取文件大小
file_size = os.path.getsize("data.txt")
print(f"文件大小:{file_size} 字节")

文件模式

模式 描述
r 只读(默认)
w 写入(覆盖)
a 追加
r+ 读写
rb 二进制只读
wb 二进制写入

文件读写

读取文件

读取整个文件

# 读取所有内容
with open("file.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)

逐行读取

# 逐行读取
with open("file.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())  # strip() 去除行尾的换行符

读取指定行

# 读取前5行
with open("file.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    first_5_lines = lines[:5]
    print(first_5_lines)

写入文件

写入内容

# 写入内容(覆盖)
with open("file.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
    f.write("第二行\n")
    f.write("第三行\n")

追加内容

# 追加内容
with open("file.txt", "a", encoding="utf-8") as f:
    f.write("追加的内容\n")
    f.write("更多追加内容\n")

写入多行

# 写入列表中的多行
lines = ["第一行", "第二行", "第三行"]

with open("file.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

文件操作示例

# 创建并写入文件
data = [
    "姓名,年龄,城市",
    "张三,25,北京",
    "李四,30,上海",
    "王五,28,广州"
]

with open("students.csv", "w", encoding="utf-8") as f:
    f.writelines("\n".join(data))

print("文件已创建!")

读取刚才创建的文件:

# 读取CSV文件
with open("students.csv", "r", encoding="utf-8") as f:
    lines = f.readlines()

for line in lines:
    print(line.strip())

异常处理

程序运行时可能会遇到各种错误,异常处理让我们能够优雅地处理这些错误。

常见异常

异常 描述
FileNotFoundError 文件不存在
PermissionError 权限不足
ValueError 值错误
TypeError 类型错误
KeyError 键不存在
IndexError 索引越界

try-except 基础

try:
    # 可能出错的代码
    result = 10 / 0
except ZeroDivisionError:
    print("除数不能为零!")

捕获多种异常

try:
    # 尝试读取文件
    with open("nonexistent.txt", "r", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print("文件不存在!")
except PermissionError:
    print("没有权限读取文件!")
except Exception as e:
    print(f"发生未知错误:{e}")

finally 块

try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("文件不存在")
finally:
    # 无论是否出错都会执行
    if 'file' in locals():
        file.close()
    print("清理工作完成")

else 块

try:
    number = int(input("请输入一个数字:"))
except ValueError:
    print("请输入有效的数字!")
else:
    # 如果没有异常,执行这里
    print(f"你输入的数字是:{number}")
    print(f"平方是:{number ** 2}")

抛出异常

def check_age(age):
    """检查年龄是否合法"""
    if age < 0:
        raise ValueError("年龄不能为负数!")
    elif age < 18:
        raise PermissionError("你还未成年!")
    else:
        print("年龄合法!")

# 调用函数
try:
    check_age(-5)
except ValueError as e:
    print(f"错误:{e}")
except PermissionError as e:
    print(f"错误:{e}")

模块与包

Python 的模块和包让我们能够组织代码,提高复用性。

导入模块

# 导入整个模块
import math
print(math.pi)  # 3.141592653589793
print(math.sqrt(16))  # 4.0

# 导入特定函数
from math import sqrt, pi
print(sqrt(25))  # 5.0
print(pi)  # 3.141592653589793

# 导入模块并取别名
import math as m
print(m.sqrt(9))  # 3.0

创建模块

创建一个新文件 mymodule.py

# mymodule.py
def greet(name):
    """问候函数"""
    print(f"你好,{name}!")

def add(a, b):
    """加法函数"""
    return a + b

PI = 3.14159

在其他文件中使用:

import mymodule

mymodule.greet("张三")
result = mymodule.add(3, 5)
print(f"3 + 5 = {result}")
print(f"PI = {mymodule.PI}")

创建包

创建包结构:

mypackage/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
    ├── __init__.py
    └── submodule.py

__init__.py 文件:

# mypackage/__init__.py
from .module1 import greet
from .module2 import add

__all__ = ["greet", "add"]

使用包:

from mypackage import greet, add
greet("张三")
print(add(3, 5))

使用标准库

import random
import time
import datetime

# random
numbers = random.sample(range(1, 100), 5)
print(f"随机数:{numbers}")

# time
start_time = time.time()
time.sleep(1)  # 休眠1秒
end_time = time.time()
print(f"耗时:{end_time - start_time:.2f}秒")

# datetime
now = datetime.datetime.now()
print(f"当前时间:{now.strftime('%Y-%m-%d %H:%M:%S')}")

综合练习

练习1:日志记录器

import datetime
import os

class Logger:
    """简单的日志记录器"""

    def __init__(self, filename="app.log"):
        self.filename = filename

    def log(self, message, level="INFO"):
        """记录日志"""
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        log_entry = f"[{timestamp}] [{level}] {message}\n"

        # 写入文件
        with open(self.filename, "a", encoding="utf-8") as f:
            f.write(log_entry)

        # 同时打印到控制台
        print(log_entry.strip())

# 使用示例
logger = Logger()
logger.log("程序启动", "INFO")
logger.log("用户登录成功", "SUCCESS")
logger.log("数据库连接失败", "ERROR")

练习2:CSV 文件处理器

import csv

class CSVProcessor:
    """CSV 文件处理器"""

    def __init__(self, filename):
        self.filename = filename

    def read_csv(self):
        """读取CSV文件"""
        data = []
        try:
            with open(self.filename, "r", encoding="utf-8") as f:
                reader = csv.DictReader(f)
                for row in reader:
                    data.append(row)
        except FileNotFoundError:
            print(f"文件 {self.filename} 不存在")
        except Exception as e:
            print(f"读取文件出错:{e}")
        return data

    def write_csv(self, data, filename=None):
        """写入CSV文件"""
        if filename is None:
            filename = self.filename

        try:
            with open(filename, "w", encoding="utf-8", newline="") as f:
                writer = csv.DictWriter(f, fieldnames=data[0].keys())
                writer.writeheader()
                writer.writerows(data)
            print(f"成功写入 {filename}")
        except Exception as e:
            print(f"写入文件出错:{e}")

# 使用示例
processor = CSVProcessor("students.csv")

# 读取
students = processor.read_csv()
for student in students:
    print(student)

# 写入
new_data = [
    {"姓名": "赵六", "年龄": 22, "城市": "深圳"},
    {"姓名": "钱七", "年龄": 26, "城市": "杭州"}
]
processor.write_csv(new_data, "new_students.csv")

练习3:文件备份工具

import os
import shutil
from datetime import datetime

class FileBackup:
    """文件备份工具"""

    def __init__(self, source_dir, backup_dir="backup"):
        self.source_dir = source_dir
        self.backup_dir = backup_dir

    def backup_file(self, filename):
        """备份单个文件"""
        try:
            source_path = os.path.join(self.source_dir, filename)
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            backup_name = f"{filename}_{timestamp}.bak"
            backup_path = os.path.join(self.backup_dir, backup_name)

            shutil.copy2(source_path, backup_path)
            print(f"已备份:{filename} -> {backup_name}")
            return True
        except Exception as e:
            print(f"备份 {filename} 失败:{e}")
            return False

    def backup_all(self):
        """备份所有文件"""
        if not os.path.exists(self.backup_dir):
            os.makedirs(self.backup_dir)

        files = os.listdir(self.source_dir)
        success_count = 0
        fail_count = 0

        for filename in files:
            if os.path.isfile(os.path.join(self.source_dir, filename)):
                if self.backup_file(filename):
                    success_count += 1
                else:
                    fail_count += 1

        print(f"\n备份完成:成功 {success_count} 个,失败 {fail_count} 个")

# 使用示例
backup = FileBackup("documents")
backup.backup_all()

总结

今天我们学习了:

文件操作:读取、写入、追加、文件模式
异常处理:try-except-finally-else,捕获不同异常
模块与包:导入模块、创建模块和包、使用标准库

重要概念

  1. with 语句:自动管理文件资源,确保文件正确关闭
  2. 异常处理:让程序更加健壮,避免意外崩溃
  3. 模块化:将代码组织成模块,提高复用性
  4. 编码:文件操作时注意使用 UTF-8 编码

常用模块

  • os:操作系统相关操作
  • sys:系统相关操作
  • datetime:日期时间处理
  • json:JSON 数据处理
  • csv:CSV 文件处理

下次学习预告

下一篇我们将学习:

  • 面向对象编程(OOP)
  • 类和对象
  • 继承、封装、多态
  • 装饰器和生成器

继续学习!掌握这些技能后,你已经能写很多实用的程序了!

动物装饰