【Python】文件处理(二)

目录

文件处理

文件与目录的属性操作

判断文件或目录是否存在

  1. os.path.exists(path)

    python 复制代码
    import os
    
    print(os.path.exists("data.txt"))   # True/False
    print(os.path.exists("folder"))     # True/False
  2. Path.exists()

    python 复制代码
    from pathlib import Path
    
    print(Path("data.txt").exists())
    print(Path("folder").exists())

判断文件类型

  1. 判断是否是文件

    • os.path.isfile(path)
    • Path.is_file()
    python 复制代码
    import os
    from pathlib import Path
    
    print(os.path.isfile("data.txt"))
    print(Path("data.txt").is_file())
  2. 判断是否是目录

    • os.path.isdir(path)
    • Path.is_dir()
    python 复制代码
    print(os.path.isdir("folder"))
    print(Path("folder").is_dir())
  3. 判断是否是符号链接

    • os.path.islink(path)
    • Path.is_symlink()

获取文件大小

  1. os.path.getsize(path)

    python 复制代码
    import os
    
    size = os.path.getsize("data.txt")
    print("文件大小:", size, "字节")
  2. Path.stat().st_size

    python 复制代码
    from pathlib import Path
    
    size = Path("data.txt").stat().st_size
    print("文件大小:", size, "字节")

获取文件时间属性

文件常见的时间属性有三种(具体含义依系统不同略有差异):

  • st_atime:最后访问时间(Access Time)
  • st_mtime:最后修改时间(Modify Time,内容被修改)
  • st_ctime:创建时间(Create Time,Windows);在 Unix/Linux 上可能表示元数据修改时间(Change Time)
  1. os.path.get*

    python 复制代码
    import os
    import time
    
    print("访问时间:", time.ctime(os.path.getatime("data.txt")))
    print("修改时间:", time.ctime(os.path.getmtime("data.txt")))
    print("创建时间:", time.ctime(os.path.getctime("data.txt")))
  2. Path.stat()

    python 复制代码
    from pathlib import Path
    import time
    
    p = Path("data.txt").stat()
    
    print("访问时间:", time.ctime(p.st_atime))
    print("修改时间:", time.ctime(p.st_mtime))
    print("创建时间:", time.ctime(p.st_ctime))

获取更多文件属性

os.stat(path)Path.stat() 可以一次性获取完整信息:

python 复制代码
import os

info = os.stat("data.txt")
print(info.st_size)    # 文件大小
print(info.st_mode)    # 权限
print(info.st_uid)     # 拥有者 ID(Unix)
print(info.st_gid)     # 用户组 ID(Unix)

结合案例:文件信息检查工具

python 复制代码
from pathlib import Path
import time

def file_info(path):
    p = Path(path)
    if not p.exists():
        print(f"{path} 不存在")
        return
    
    print("名称:", p.name)
    print("类型:", "目录" if p.is_dir() else "文件")
    print("大小:", p.stat().st_size, "字节")
    print("访问时间:", time.ctime(p.stat().st_atime))
    print("修改时间:", time.ctime(p.stat().st_mtime))
    print("创建时间:", time.ctime(p.stat().st_ctime))

file_info("data.txt")

文件权限操作

什么是文件权限?

在操作系统里,文件通常有 读 ®、写 (w)、执行 (x) 三种权限,针对 不同的用户类别

  • u (user):文件所有者
  • g (group):同组用户
  • o (others):其他用户
  • a (all):所有用户(user + group + others)

示例:Linux 中执行 ls -l

复制代码
-rw-r--r--  1 user group  1024 Sep 25  data.txt

解释:

  • rw- → 所有者可以读写
  • r-- → 同组用户只能读
  • r-- → 其他用户只能读

修改文件权限

  1. os.chmod(path, mode)

    • 作用:修改文件权限(仅限 Unix 系统有效,Windows 对执行权限的处理有限)。
    • mode :用 八进制数字 表示权限,比如:
      • 0o777 → 所有人可读写执行
      • 0o644 → 所有者可读写,其他人可读
      • 0o600 → 仅所有者可读写

    示例:

    python 复制代码
    import os
    
    # 把 data.txt 权限改为 644 (rw-r--r--)
    os.chmod("data.txt", 0o644)
  2. 使用 stat 模块更直观

    stat 提供了一些常量,可以组合使用。

    python 复制代码
    import os, stat
    
    # 设置成 只读
    os.chmod("data.txt", stat.S_IREAD)
    
    # 设置成 可写
    os.chmod("data.txt", stat.S_IWRITE)
    
    # 设置成 可执行
    os.chmod("script.sh", stat.S_IEXEC)
    
    # 组合权限 (读 + 写)
    os.chmod("config.ini", stat.S_IREAD | stat.S_IWRITE)

检查权限

os.access(path, mode)

  • 作用:检查当前用户是否有权限访问某个文件。
  • mode 参数
    • os.F_OK → 文件是否存在
    • os.R_OK → 是否可读
    • os.W_OK → 是否可写
    • os.X_OK → 是否可执行

示例:

python 复制代码
import os

print(os.access("data.txt", os.F_OK))  # 是否存在
print(os.access("data.txt", os.R_OK))  # 是否可读
print(os.access("data.txt", os.W_OK))  # 是否可写
print(os.access("script.sh", os.X_OK)) # 是否可执行

文件所有权(Linux/Unix 常用)

在 Linux/Unix 系统中,每个文件都有 用户 ID (uid)组 ID (gid)

  1. 查看所有者

    python 复制代码
    import os
    
    info = os.stat("data.txt")
    print("用户 ID:", info.st_uid)
    print("组 ID:", info.st_gid)
  2. 修改所有者(需要 root 权限)

    python 复制代码
    import os
    
    # 把文件的所有者改为用户 ID 1000,组 ID 1000
    os.chown("data.txt", 1000, 1000)

    在 Windows 系统中,os.chown() 不可用。

跨平台注意事项

  • Linux/macOS :支持完整的 chmodchown、权限检查。
  • Windows :文件系统权限机制不同,部分操作(如 chown、执行权限)无效。
  • 如果要写跨平台代码,推荐:
    • os.access() 来做权限检测
    • 避免依赖 chown,Windows 不支持

综合示例:权限管理工具

python 复制代码
import os, stat

def check_permissions(path):
    print(f"检查 {path} 权限:")
    print("存在:", os.access(path, os.F_OK))
    print("可读:", os.access(path, os.R_OK))
    print("可写:", os.access(path, os.W_OK))
    print("可执行:", os.access(path, os.X_OK))

def set_readonly(path):
    os.chmod(path, stat.S_IREAD)
    print(f"{path} 已设为只读")

def set_writable(path):
    os.chmod(path, stat.S_IREAD | stat.S_IWRITE)
    print(f"{path} 已设为可写")

check_permissions("data.txt")
set_readonly("data.txt")
check_permissions("data.txt")

文件与目录的高级操作

文件复制与移动(shutil 模块)

shutil 提供了更强大的文件操作接口,常用于批量处理文件。

  1. 复制文件

    • shutil.copy(src, dst)
      复制文件内容 + 权限(不包含修改时间、元数据)。
    • shutil.copy2(src, dst)
      复制文件内容 + 权限 + 时间戳等元数据。
    python 复制代码
    import shutil
    
    # 简单复制
    shutil.copy("a.txt", "backup_a.txt")
    
    # 保留元数据复制
    shutil.copy2("a.txt", "backup_with_meta.txt")
  2. 复制整个目录

    • shutil.copytree(src, dst)
      递归复制目录及子目录内容。
    python 复制代码
    shutil.copytree("my_folder", "backup_folder")

    注意:目标目录 不能已存在 ,否则会报错(Python 3.8+ 可以加 dirs_exist_ok=True 来覆盖)。

  3. 移动文件/目录

    • shutil.move(src, dst)
      可以移动文件或目录,相当于剪切操作。
    python 复制代码
    # 移动文件
    shutil.move("a.txt", "subdir/a.txt")
    
    # 移动目录
    shutil.move("backup_folder", "archive/backup_folder")

删除操作

除了前面 os.remove()os.rmdir(),更常用的是 shutil

  • shutil.rmtree(path) → 删除整个目录树(包括所有子目录和文件)
python 复制代码
import shutil

shutil.rmtree("backup_folder")  # 小心!不可逆

文件/目录信息(元数据)

有时候需要获取文件属性(大小、创建时间、修改时间等):

  1. 使用 os.stat()

    python 复制代码
    import os
    import time
    
    stat_info = os.stat("a.txt")
    
    print("大小:", stat_info.st_size, "字节")
    print("最后修改时间:", time.ctime(stat_info.st_mtime))
    print("最后访问时间:", time.ctime(stat_info.st_atime))
    print("创建时间:", time.ctime(stat_info.st_ctime))
  2. 使用 pathlib.Path.stat()

    python 复制代码
    from pathlib import Path
    
    p = Path("a.txt")
    info = p.stat()
    
    print("大小:", info.st_size)
    print("修改时间:", info.st_mtime)

遍历目录树

如果你需要扫描所有文件,推荐用 os.walk()pathlib.rglob()

  1. os.walk()

    python 复制代码
    import os
    
    for root, dirs, files in os.walk("my_folder"):
        print("当前目录:", root)
        print("子目录:", dirs)
        print("文件:", files)
  2. pathlib.Path.rglob()

    python 复制代码
    from pathlib import Path
    
    p = Path("my_folder")
    
    # 递归查找所有 txt 文件
    for file in p.rglob("*.txt"):
        print(file)

路径操作(进阶)

除了前面 os.pathjoinsplitpathlib 提供了更优雅的方式:

python 复制代码
from pathlib import Path

p = Path("my_folder") / "subdir" / "a.txt"

print("完整路径:", p.resolve())
print("父目录:", p.parent)
print("文件名:", p.name)
print("后缀:", p.suffix)
print("是否存在:", p.exists())

临时文件与目录

有时候需要在程序运行时创建临时文件/目录,Python 提供了 tempfile 模块:

python 复制代码
import tempfile

# 创建临时文件
with tempfile.TemporaryFile(mode="w+t") as tmp:
    tmp.write("临时内容")
    tmp.seek(0)
    print(tmp.read())  # 程序结束后自动删除

# 创建临时目录
with tempfile.TemporaryDirectory() as tmpdir:
    print("临时目录:", tmpdir)

压缩与解压

shutil 还支持压缩与解压(ZIP、TAR 等格式):

python 复制代码
import shutil

# 压缩目录为 zip 文件
shutil.make_archive("backup", "zip", "my_folder")

# 解压缩
shutil.unpack_archive("backup.zip", "unpacked_folder")

文件内容格式的操作

JSON 文件操作

在实际开发中,JSON(JavaScript Object Notation)是最常用的数据交换格式,尤其在配置文件、前后端通信、存储结构化数据时非常常见。

Python 内置的 json 模块就能轻松读写 JSON 文件。

什么是 JSON?

  • JSON 是一种 轻量级数据交换格式,结构类似 Python 的字典。
  • 数据类型对应关系
JSON 类型 Python 类型
object dict
array list
string str
number int / float
true True
false False
null None

读写 JSON 的基础方法

  1. Python 对象 ↔ JSON 字符串

    python 复制代码
    import json
    
    data = {
        "name": "Alice",
        "age": 25,
        "is_student": False,
        "courses": ["Math", "English"],
        "address": {"city": "Tokyo", "zip": "100-0001"}
    }
    
    # Python 对象 → JSON 字符串
    json_str = json.dumps(data, ensure_ascii=False, indent=4)
    print("JSON 字符串:\n", json_str)
    
    # JSON 字符串 → Python 对象
    parsed = json.loads(json_str)
    print("解析后的 Python 对象:", parsed)

    参数说明:

    • ensure_ascii=False → 让中文正常显示,而不是 \uXXXX 形式。
    • indent=4 → 美化缩进,便于阅读。
  2. 写入 JSON 文件

    python 复制代码
    # 写入 JSON 文件
    with open("data.json", "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=4)
  3. 读取 JSON 文件

    python 复制代码
    # 读取 JSON 文件
    with open("data.json", "r", encoding="utf-8") as f:
        loaded_data = json.load(f)
    
    print("从文件中读取的数据:", loaded_data)

高级用法

  1. 处理复杂对象(自定义类)

    默认情况下,json 不能直接序列化自定义对象,需要提供 编码和解码方法

    python 复制代码
    import json
    from datetime import datetime
    
    class Student:
        def __init__(self, name, age, enroll_date):
            self.name = name
            self.age = age
            self.enroll_date = enroll_date
    
    s = Student("Bob", 20, datetime.now())
    
    # 自定义序列化
    def encode_student(obj):
        if isinstance(obj, Student):
            return {"name": obj.name, "age": obj.age, "enroll_date": obj.enroll_date.isoformat()}
        if isinstance(obj, datetime):
            return obj.isoformat()
        raise TypeError("类型不支持序列化")
    
    json_str = json.dumps(s, default=encode_student, ensure_ascii=False, indent=4)
    print(json_str)
  2. 反序列化回对象

    python 复制代码
    def decode_student(d):
        if "enroll_date" in d:
            return Student(d["name"], d["age"], datetime.fromisoformat(d["enroll_date"]))
        return d
    
    # 从 JSON 恢复为 Student 对象
    student_obj = json.loads(json_str, object_hook=decode_student)
    print(student_obj.name, student_obj.age, student_obj.enroll_date)
  3. 按行读取 JSON(大文件处理)

    如果 JSON 文件很大,可以逐行读取,每行一个 JSON 对象(常见于日志存储)。

    python 复制代码
    with open("bigdata.json", "r", encoding="utf-8") as f:
        for line in f:
            record = json.loads(line)
            print(record)
  4. 合并多个 JSON 文件

    python 复制代码
    import json
    from pathlib import Path
    
    merged_data = []
    
    for file in Path("json_files").glob("*.json"):
        with open(file, "r", encoding="utf-8") as f:
            merged_data.append(json.load(f))
    
    with open("merged.json", "w", encoding="utf-8") as f:
        json.dump(merged_data, f, ensure_ascii=False, indent=4)

实战小案例:记事本存储 JSON

python 复制代码
import json
from datetime import datetime

NOTE_FILE = "notes.json"

def add_note(title, content):
    try:
        with open(NOTE_FILE, "r", encoding="utf-8") as f:
            notes = json.load(f)
    except FileNotFoundError:
        notes = []

    notes.append({
        "title": title,
        "content": content,
        "time": datetime.now().isoformat()
    })

    with open(NOTE_FILE, "w", encoding="utf-8") as f:
        json.dump(notes, f, ensure_ascii=False, indent=4)

def show_notes():
    try:
        with open(NOTE_FILE, "r", encoding="utf-8") as f:
            notes = json.load(f)
    except FileNotFoundError:
        notes = []
    for n in notes:
        print(f"[{n['time']}] {n['title']}: {n['content']}")

# 测试
add_note("学习 Python", "今天学了 JSON 文件操作")
show_notes()

CSV 文件操作

CSV(Comma-Separated Values,逗号分隔值)是最常见的数据存储格式之一,尤其在 数据分析、Excel 导入导出、数据库备份 等场景非常常见。

Python 提供了内置的 csv 模块 来处理 CSV 文件。

什么是 CSV?

  • CSV 本质上是一个 文本文件 ,通过 逗号(或其他分隔符) 分隔字段。

  • 常见格式:

    name,age,city
    Alice,25,Tokyo
    Bob,30,Beijing
    Charlie,22,New York

写入 CSV 文件

  1. 写入行数据

    python 复制代码
    import csv
    
    data = [
        ["name", "age", "city"],
        ["Alice", 25, "Tokyo"],
        ["Bob", 30, "Beijing"],
        ["Charlie", 22, "New York"]
    ]
    
    with open("people.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerows(data)  # 写入多行

    注意:

    • newline="" → 避免写入空行(Windows 特别需要)。
    • writerow() → 写入单行。
    • writerows() → 写入多行。
  2. 使用字典写入(推荐)

    python 复制代码
    import csv
    
    data = [
        {"name": "Alice", "age": 25, "city": "Tokyo"},
        {"name": "Bob", "age": 30, "city": "Beijing"},
        {"name": "Charlie", "age": 22, "city": "New York"}
    ]
    
    with open("people_dict.csv", "w", newline="", encoding="utf-8") as f:
        fieldnames = ["name", "age", "city"]
        writer = csv.DictWriter(f, fieldnames=fieldnames)
    
        writer.writeheader()   # 写入表头
        writer.writerows(data) # 写入数据

读取 CSV 文件

  1. 逐行读取

    python 复制代码
    import csv
    
    with open("people.csv", "r", encoding="utf-8") as f:
        reader = csv.reader(f)
        for row in reader:
            print(row)  # 每一行是一个列表

    输出:

    复制代码
    ['name', 'age', 'city']
    ['Alice', '25', 'Tokyo']
    ['Bob', '30', 'Beijing']
    ['Charlie', '22', 'New York']
  2. 使用字典方式读取

    复制代码
    import csv
    
    with open("people_dict.csv", "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            print(row)  # 每一行是一个字典

    输出:

    python 复制代码
    {'name': 'Alice', 'age': '25', 'city': 'Tokyo'}
    {'name': 'Bob', 'age': '30', 'city': 'Beijing'}
    {'name': 'Charlie', 'age': '22', 'city': 'New York'}

    注意:所有内容会被读成字符串,需要自己转类型。

高级用法

  1. 自定义分隔符

    有时不是逗号,而是 \t(制表符)或 ;

    python 复制代码
    with open("tab_file.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, delimiter="\t")
        writer.writerow(["name", "age", "city"])
        writer.writerow(["Alice", 25, "Tokyo"])
  2. 自定义分隔符

    有时不是逗号,而是 \t(制表符)或 ;

    python 复制代码
    with open("tab_file.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, delimiter="\t")
        writer.writerow(["name", "age", "city"])
        writer.writerow(["Alice", 25, "Tokyo"])
  3. 转换为列表/字典

    python 复制代码
    with open("people.csv", "r", encoding="utf-8") as f:
        reader = csv.reader(f)
        data = list(reader)  # 转为列表
    print(data)
    
    with open("people_dict.csv", "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        data = list(reader)  # 转为字典列表
    print(data)

实战案例:成绩表统计

假设有一个 scores.csv 文件:

复制代码
name,math,english,science
Alice,90,85,92
Bob,78,88,80
Charlie,95,92,89

我们计算每个人的平均分:

python 复制代码
import csv

with open("scores.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        math = int(row["math"])
        eng = int(row["english"])
        sci = int(row["science"])
        avg = (math + eng + sci) / 3
        print(f"{row['name']} 平均分: {avg:.2f}")

输出:

复制代码
Alice 平均分: 89.00
Bob 平均分: 82.00
Charlie 平均分: 92.00

Excel 文件操作

安装库

如果还没有安装:

python 复制代码
pip install openpyxl

创建 Excel 文件

python 复制代码
from openpyxl import Workbook

# 创建工作簿
wb = Workbook()

# 激活默认工作表
ws = wb.active
ws.title = "学生成绩"

# 写入单元格数据
ws["A1"] = "姓名"
ws["B1"] = "数学"
ws["C1"] = "英语"

ws.append(["Alice", 90, 85])
ws.append(["Bob", 78, 88])
ws.append(["Charlie", 95, 92])

# 保存文件
wb.save("scores.xlsx")

注意:

  • ws["A1"] = "姓名" → 直接赋值写入。
  • ws.append([...]) → 添加一行。

读取 Excel 文件

python 复制代码
from openpyxl import load_workbook

# 打开 Excel 文件
wb = load_workbook("scores.xlsx")

# 获取工作表
ws = wb["学生成绩"]

# 遍历行
for row in ws.iter_rows(values_only=True):
    print(row)

输出:

复制代码
('姓名', '数学', '英语')
('Alice', 90, 85)
('Bob', 78, 88)
('Charlie', 95, 92)

获取单元格信息

python 复制代码
# 获取单个单元格
cell = ws["B2"]
print("值:", cell.value)
print("行:", cell.row, "列:", cell.column)

# 遍历列
for col in ws.iter_cols(min_col=2, max_col=3, values_only=True):
    print(col)

修改 Excel

python 复制代码
# 修改单元格
ws["C2"] = 95  # 把 Alice 的英语改成 95

# 插入新行
ws.insert_rows(2)

# 删除列
ws.delete_cols(2)

wb.save("scores_updated.xlsx")

样式设置(美化表格)

python 复制代码
from openpyxl.styles import Font, Alignment, PatternFill

# 设置字体
ws["A1"].font = Font(bold=True, color="FFFFFF")

# 设置背景色
ws["A1"].fill = PatternFill(start_color="4F81BD", end_color="4F81BD", fill_type="solid")

# 居中对齐
ws["A1"].alignment = Alignment(horizontal="center", vertical="center")

wb.save("scores_styled.xlsx")

多个工作表操作

python 复制代码
# 新建工作表
ws2 = wb.create_sheet("总分")

# 写入数据
ws2["A1"] = "姓名"
ws2["B1"] = "总分"

# 从学生成绩表读取并计算总分
for row in ws.iter_rows(min_row=2, values_only=True):
    name, math, english = row
    ws2.append([name, math + english])

wb.save("scores_with_total.xlsx")

实战案例:统计成绩并排序

python 复制代码
from openpyxl import load_workbook

wb = load_workbook("scores.xlsx")
ws = wb.active

# 提取数据
data = []
for row in ws.iter_rows(min_row=2, values_only=True):
    name, math, english = row
    total = math + english
    data.append((name, math, english, total))

# 排序(按总分降序)
data.sort(key=lambda x: x[3], reverse=True)

# 写入新表
ws_sorted = wb.create_sheet("排序结果")
ws_sorted.append(["姓名", "数学", "英语", "总分"])
for row in data:
    ws_sorted.append(row)

wb.save("scores_sorted.xlsx")

高级功能(常用扩展)

  • 公式支持ws["D2"] = "=B2+C2"(Excel 会自动计算)
  • 合并单元格ws.merge_cells("A1:C1")
  • 冻结窗格ws.freeze_panes = "A2"(冻结第一行)
  • 自动调整列宽 :需手动计算字符串长度,再设置 column_dimensions
相关推荐
先知后行。3 小时前
QT实现计算器
开发语言·qt
掘根3 小时前
【Qt】常用控件3——显示类控件
开发语言·数据库·qt
万粉变现经纪人5 小时前
如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘tokenizers’ 问题
python·selenium·测试工具·scrapy·beautifulsoup·fastapi·pip
西阳未落7 小时前
C++基础(21)——内存管理
开发语言·c++·面试
编程武士7 小时前
从50ms到30ms:YOLOv10部署中图像预处理的性能优化实践
人工智能·python·yolo·性能优化
我的xiaodoujiao7 小时前
Windows系统Web UI自动化测试学习系列2--环境搭建--Python-PyCharm-Selenium
开发语言·python·测试工具
callJJ7 小时前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(2)
java·开发语言·后端·spring·ioc·di
hsjkdhs9 小时前
万字详解C++之构造函数析构函数
开发语言·c++
Lin_Aries_042110 小时前
容器化简单的 Java 应用程序
java·linux·运维·开发语言·docker·容器·rpc