← 返回首页 | ← 返回教程列表

Python学习教程 - 第五课:文件操作,让数据持久化!

欢迎回来!🎉 这节课我们要学习如何与文件打交道——让程序可以保存数据读取数据,就像给数据找个家!


复习一下前四节课

前四节课我们学会了: - 变量和基本数据类型 - 条件判断和循环 - 列表和字典 - 函数(代码的魔法师)

这节课我们要学习如何让程序和文件交互,实现数据的持久化!


第一个知识点:为什么需要文件操作?

在之前的课程中,我们的数据都保存在内存里,程序一关闭,数据就消失了。

文件可以让数据永久保存在硬盘上,下次打开程序还能用!

文件操作的常见场景

保存游戏进度:下次接着玩
记录日志:程序运行时的信息
读取配置:程序的设置
处理数据:读取CSV、Excel等数据文件
生成报告:把结果保存成文件


第二个知识点:打开和关闭文件

打开文件:open()函数

# 打开文件的基本语法
file = open("文件名", "模式")

# 操作文件...

# 关闭文件
file.close()

文件打开模式

模式 说明
r 读取模式(默认),文件必须存在
w 写入模式,文件不存在则创建,存在则覆盖
a 追加模式,文件不存在则创建,存在则在末尾追加
r+ 读写模式,文件必须存在
w+ 读写模式,文件不存在则创建,存在则覆盖
a+ 读写模式,文件不存在则创建,存在则在末尾追加

示例:打开一个文件

# 打开一个文件用于读取
f = open("test.txt", "r")
# 操作文件...
f.close()  # 记得关闭!

更好的方式:with语句(推荐!)

# 使用with语句,会自动关闭文件
with open("test.txt", "r") as f:
    # 在这里操作文件
    pass  # pass表示什么都不做

# 文件已经自动关闭了,不用手动调用close()

为什么推荐with语句? - 自动关闭文件,不会忘记 - 更安全,即使出错也会关闭 - 代码更简洁


第三个知识点:读取文件

读取整个文件:read()

# 读取整个文件内容
with open("test.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)

按行读取:readline()

# 逐行读取
with open("test.txt", "r", encoding="utf-8") as f:
    line1 = f.readline()
    line2 = f.readline()
    print("第一行:", line1.strip())  # strip()去掉换行符
    print("第二行:", line2.strip())

读取所有行:readlines()

# 读取所有行到列表
with open("test.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    print(f"文件共有{len(lines)}行")

    # 遍历每一行
    for i, line in enumerate(lines, 1):
        print(f"第{i}行: {line.strip()}")

直接遍历文件对象(最简单!)

# 直接用for循环遍历文件
with open("test.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

第四个知识点:写入文件

写入模式:w(覆盖)

# 写入内容(会覆盖原有内容)
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Hello, World!\n")
    f.write("这是第二行\n")
    f.write("Python文件操作很简单!\n")

追加模式:a(不覆盖)

# 追加内容(不会覆盖原有内容)
with open("output.txt", "a", encoding="utf-8") as f:
    f.write("这是追加的内容\n")
    f.write("不会覆盖原来的内容\n")

写入多行:writelines()

# 写入多行内容
lines = [
    "第一行\n",
    "第二行\n",
    "第三行\n"
]

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

第五个知识点:文件路径和目录操作

os模块:操作系统相关功能

import os

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

# 列出目录内容
files = os.listdir(".")
print("目录内容:", files)

# 创建目录
os.makedirs("data", exist_ok=True)  # exist_ok=True表示如果存在就不报错

# 检查路径是否存在
print("'data'目录存在吗?", os.path.exists("data"))

# 检查是文件还是目录
print("是文件吗?", os.path.isfile("test.txt"))
print("是目录吗?", os.path.isdir("data"))

# 路径拼接
full_path = os.path.join("data", "test.txt")
print("完整路径:", full_path)

pathlib模块:更现代的路径操作(推荐!)

from pathlib import Path

# 创建Path对象
current_path = Path.cwd()
print("当前目录:", current_path)

# 列出目录内容
files = list(current_path.glob("*"))  # *表示所有文件
print("目录内容:", files)

# 创建目录
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)

# 检查路径
print("'data'目录存在吗?", data_dir.exists())
print("是文件吗?", data_dir.is_file())
print("是目录吗?", data_dir.is_dir())

# 路径拼接
file_path = data_dir / "test.txt"  # 使用/操作符
print("完整路径:", file_path)

第六个知识点:处理不同类型的文件

CSV文件:逗号分隔值

import csv

# 写入CSV文件
data = [
    ["姓名", "年龄", "城市"],
    ["小明", 18, "北京"],
    ["小红", 17, "上海"],
    ["小刚", 19, "广州"]
]

with open("students.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerows(data)

# 读取CSV文件
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# 使用字典方式读写CSV
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['姓名']} - {row['年龄']}岁 - {row['城市']}")

JSON文件:JavaScript对象表示法

import json

# 数据
student = {
    "name": "小明",
    "age": 18,
    "city": "北京",
    "hobbies": ["读书", "游泳", "编程"],
    "scores": {"数学": 90, "语文": 85, "英语": 88}
}

# 写入JSON文件
with open("student.json", "w", encoding="utf-8") as f:
    json.dump(student, f, ensure_ascii=False, indent=2)

# 读取JSON文件
with open("student.json", "r", encoding="utf-8") as f:
    data = json.load(f)
    print(data)
    print(f"姓名: {data['name']}")
    print(f"爱好: {data['hobbies']}")
    print(f"数学成绩: {data['scores']['数学']}")

二进制文件:图片、视频等

# 复制图片(二进制文件)
with open("original.jpg", "rb") as source:  # rb表示读取二进制
    with open("copy.jpg", "wb") as target:  # wb表示写入二进制
        target.write(source.read())

第七个知识点:异常处理

文件操作可能会出错,我们需要处理异常!

try:
    with open("不存在的文件.txt", "r", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print("错误:文件不存在!")
except PermissionError:
    print("错误:没有权限访问文件!")
except Exception as e:
    print(f"发生未知错误:{e}")
else:
    print("文件读取成功!")
finally:
    print("无论成功或失败都会执行这里")

综合练习1:学生成绩管理系统

让我们创建一个实用的程序!

import json
from pathlib import Path

class GradeManager:
    def __init__(self, data_file="grades.json"):
        self.data_file = Path(data_file)
        self.grades = self.load_grades()

    def load_grades(self):
        """加载成绩数据"""
        if self.data_file.exists():
            with open(self.data_file, "r", encoding="utf-8") as f:
                return json.load(f)
        return {}

    def save_grades(self):
        """保存成绩数据"""
        with open(self.data_file, "w", encoding="utf-8") as f:
            json.dump(self.grades, f, ensure_ascii=False, indent=2)

    def add_student(self, name, scores):
        """添加学生"""
        self.grades[name] = scores
        self.save_grades()
        print(f"已添加学生:{name}")

    def update_student(self, name, scores):
        """更新学生成绩"""
        if name in self.grades:
            self.grades[name] = scores
            self.save_grades()
            print(f"已更新学生:{name}")
        else:
            print(f"学生{name}不存在!")

    def get_student(self, name):
        """获取学生信息"""
        if name in self.grades:
            return self.grades[name]
        return None

    def list_all(self):
        """列出所有学生"""
        print("\n=== 所有学生成绩 ===")
        for name, scores in self.grades.items():
            avg_score = sum(scores.values()) / len(scores)
            print(f"{name}: {scores}, 平均分: {avg_score:.1f}")

    def get_average(self, subject):
        """计算某门课的平均分"""
        scores = []
        for student_scores in self.grades.values():
            if subject in student_scores:
                scores.append(student_scores[subject])

        if scores:
            return sum(scores) / len(scores)
        return None

# 使用成绩管理系统
manager = GradeManager()

# 添加学生
manager.add_student("小明", {"数学": 90, "语文": 85, "英语": 88})
manager.add_student("小红", {"数学": 95, "语文": 92, "英语": 90})
manager.add_student("小刚", {"数学": 85, "语文": 80, "英语": 82})

# 列出所有学生
manager.list_all()

# 计算数学平均分
math_avg = manager.get_average("数学")
print(f"\n数学平均分: {math_avg:.1f}")

# 查询某个学生
xiaoming = manager.get_student("小明")
print(f"\n小明的成绩: {xiaoming}")

综合练习2:日志系统

import datetime
from pathlib import Path

class Logger:
    def __init__(self, log_dir="logs"):
        self.log_dir = Path(log_dir)
        self.log_dir.mkdir(exist_ok=True)

    def get_log_file(self):
        """获取今天的日志文件名"""
        today = datetime.date.today().strftime("%Y-%m-%d")
        return self.log_dir / f"{today}.log"

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

        with open(self.get_log_file(), "a", encoding="utf-8") as f:
            f.write(log_line)

        print(log_line.strip())

    def info(self, message):
        """记录信息"""
        self.log("INFO", message)

    def warning(self, message):
        """记录警告"""
        self.log("WARNING", message)

    def error(self, message):
        """记录错误"""
        self.log("ERROR", message)

    def debug(self, message):
        """记录调试信息"""
        self.log("DEBUG", message)

# 使用日志系统
logger = Logger()

logger.info("程序启动")
logger.warning("这是一个警告信息")
logger.error("发生了一个错误")
logger.debug("调试信息")
logger.info("程序结束")

第五课小结

今天我们学会了:

文件操作的重要性:数据持久化
打开和关闭文件:open()和with语句
读取文件:read()、readline()、readlines()
写入文件:write()、writelines()
目录操作:os模块和pathlib模块
处理不同文件类型:CSV、JSON、二进制文件
异常处理:让程序更健壮


课后练习 ✏️

  1. 写一个程序,统计一个文本文件中有多少个字符、多少个单词、多少行
  2. 写一个程序,把一个文件的内容复制到另一个文件
  3. 写一个程序,读取一个CSV文件,计算每列的平均值
  4. 写一个程序,把多个JSON文件合并成一个
  5. 写一个简易的日记本程序,可以保存和读取日记

下节课预告:我们会学习模块和包,如何组织代码和使用别人写好的库!

继续加油!你已经掌握了Python编程的核心技能!💪