Python从入门到实战(十五):文件操作与目录管理

目录

一、为什么需要文件操作

[1. 文件基础概念](#1. 文件基础概念)

[2. 文件的分类](#2. 文件的分类)

[3. 为什么程序需要操作文件](#3. 为什么程序需要操作文件)

[4. Python 操作文件的流程](#4. Python 操作文件的流程)

二、文件路径

[1. 绝对路径与相对路径](#1. 绝对路径与相对路径)

[2. 路径分隔符](#2. 路径分隔符)

[3. 跨平台路径拼接](#3. 跨平台路径拼接)

三、打开文件

[1. open() 函数](#1. open() 函数)

[2. 文件打开模式](#2. 文件打开模式)

四、读取文件

[1. read()](#1. read())

[2. readline()](#2. readline())

[3. readlines()](#3. readlines())

[4. 文件对象遍历](#4. 文件对象遍历)

[5. 读取方式对比与最佳实践](#5. 读取方式对比与最佳实践)

五、关闭文件

[1. 为什么必须关闭文件](#1. 为什么必须关闭文件)

[2. close()](#2. close())

[3. with 语句](#3. with 语句)

[4. with 语句原理](#4. with 语句原理)

六、写入文件

[1. 基础写入 API](#1. 基础写入 API)

[2. flush()](#2. flush())

七、目录操作

[1. 当前工作目录](#1. 当前工作目录)

[2. 路径状态判断](#2. 路径状态判断)

[3. 目录与文件的创建、删除及重命名](#3. 目录与文件的创建、删除及重命名)

[4. 遍历目录](#4. 遍历目录)

总结


一、为什么需要文件操作

在前面的学习中,我们所编写的所有 Python 代码、创建的各种变量以及计算的中间结果,都存在于系统的运行内存中。然而在真实生产环境中,数据不能仅临时存在

无论是保存系统配置、记录运行日志,还是读取海量数据集,程序都必须持久化存储。本篇博客将系统梳理 Python 中文件操作与目录管理的机制与规范


1. 文件基础概念

计算机的存储体系在物理层面主要分为两大类:

  • 运行内存

    • 特点 :读写速度极快,但具备易失性

    • 机制:我们在 Python 代码中创建的所有变量、列表、字典等对象,全部驻留在 RAM 中。一旦程序运行结束、进程被销毁,或者电脑关机断电,RAM 中的所有数据就会被立刻清空

  • 外存/持久化存储(硬盘/SSD 等)

    • 特点 :读写速度相对较慢,但具备非易失性

    • 机制:数据被写入磁性介质中。即使关机断电,数据依然完好无损地存在

文件的存在,就是为了在持久化存储介质上,为数据提供一个被长期保存和再利用的载体

什么是文件

从操作系统的角度来看,文件是存储在非易失性介质上的、具有文件名的一组有序字节序列

操作系统通过文件系统(来管理这些物理字节,并为上层应用(例如 Python 解释器)提供统一的读写抽象接口


2. 文件的分类

在计算机底层,所有文件本质上都是由 0 和 1 组成的二进制字节流。但在应用层面上,根据字节编码解析方式的不同,文件通常被分为两大类:

文本文件

  • 特征:底层字节流严格按照某种固定的字符编码表(如 UTF-8)进行组织

  • 常见类型:.txt、.py、.json、.csv、.md、.html

  • 解析方式:可以直接用通用的文本编辑器(如记事本)打开,并被人眼正常识读

二进制文件

  • 特征:底层字节流不遵循文本字符编码规范,而是按照某种特定软件自定义的二进制结构进行序列化

  • 常见类型:.jpg、.png、.mp4、.pdf、.zip、.pyc(Python 编译字节码)

  • 解析方式:如果强制用文本编辑器打开,由于解释器无法匹配对应的字符集,通常会显示为无意义的乱码。必须由能够理解其特定格式规范的专有软件(如图片查看器)进行解码


3. 为什么程序需要操作文件

在现代软件工程中,程序进行文件读写的主要目的包括:

  • 数据持久化:将用户注册信息、计算结果落盘,防止因程序崩溃或重启导致数据丢失

  • 配置管理:从外部文件(如 config.json)加载启动参数,避免将硬编码写死在程序源码中

  • 系统日志:将系统运行状态、警告和异常堆栈信息实时写入日志文件,以便事后溯源排查问题

  • 数据交换:通过导出 CSV、Excel 或 JSON 文件,将数据提交给其他系统或团队使用


4. Python 操作文件的流程

无论是在 Python、C 还是 Java 中,应用程序操作文件的底层机制都受到操作系统的统一约束。Python 封装了这一流程,其标准的三步法如下:

  • 打开文件 :向操作系统发起系统调用,内核检查权限与文件路径,在内存中为该文件创建数据结构并返回一个文件句柄

  • 读写数据:通过返回的文件句柄,向缓冲区读取数据或写入数据

  • 关闭文件:向操作系统发送释放通知,强制将缓冲区中残留的数据刷新到磁盘,并回收操作系统的文件句柄资源

二、文件路径

在向操作系统发起文件打开请求之前,程序必须明确指定目标文件在文件系统中的存储路径


1. 绝对路径与相对路径

在计算机文件系统中,路径的指定方式分为绝对路径相对路径两种形式

绝对路径

  • 定义:从操作系统文件系统的根目录开始,完整且明确地描述文件在硬盘中的具体位置

  • 特征

    • Windows:以盘符开头,例如 C:\Users\Admin\Projects\data.txt

    • Linux / macOS :以斜杠 / 开头,例如 /home/user/projects/data.txt

  • 优缺点

    • 优点:物理定位唯一且精确,不受当前程序执行位置变动的影响

    • 缺点:缺乏移植性。代码一旦更换运行环境或换到另一台电脑,路径极大概率会失效

相对路径

  • 定义:以程序当前工作目录为基准出发点,描述目标文件的相对物理位置

  • 标记

    • . 代表当前工作目录本身

    • .. 代表上一级父目录

  • 示例

    • data.txt 或 ./data.txt:表示位于当前工作目录下的 data.txt

    • ../config/settings.json:表示位于当前工作目录的父目录中 config 文件夹内的 settings.json

  • 优缺点

    • 优点:移植性极强。只要项目内部的文件结构保持不变,整个项目文件夹移动到任何位置或任何操作系统上,代码均可直接运行

    • 缺点:依赖当前工作目录。如果在命令行中切换了运行路径再启动程序,相对路径可能会解析失败


2. 路径分隔符

不同的操作系统在底层对于路径分隔符的设计存在差异:

  • Linux / macOS:使用正斜杠 / 作为路径分隔符(如 /usr/bin/python)

  • Windows :使用反斜杠 \ 作为路径分隔符(如 C:\Windows\System32)

常见问题:Python 字符串转义

在 Python 代码中,反斜杠被定义为转义字符。如果直接在普通字符串中使用 Windows 风格的路径,极易触发解析错误:

python 复制代码
# \n 被解析为换行符,\t 被解析为制表符
path = "C:\new_folder\test.txt" 
print(path)

输出结果:

解决方案:

  1. 使用 Raw 字符串:在字符串引号前加上字母 r,显式告知 Python 解释器禁绝内部所有的转义行为

    python 复制代码
    path = r"C:\new_folder\test.txt"
  2. 统一使用正斜杠:Python 内置的路径解析器在 Windows 平台下具备自动兼容能力,统一使用正斜杠可以安全做到跨平台通行

    python 复制代码
    path = "C:/new_folder/test.txt"  # Windows 与 Linux/macOS 通用

3. 跨平台路径拼接

在实际工程项目中,硬编码写死字符串形式的路径是严重违反规范的行为。例如,手写

folder + "/" + filename 在 Windows 系统下可能会导致路径格式混淆

为了优雅解决跨平台路径拼接问题,Python 在标准库 os 中提供了路径处理工具 os.path.join()

  • 机制 :os.path.join() 会根据当前代码所运行的操作系统类型,自动识别并选用该系统对应的路径分隔符来进行安全拼接
python 复制代码
import os

base_dir = "projects"
sub_dir = "data"
filename = "logs.txt"

# 自动依据当前操作系统选用分隔符(Windows 下为 \,Linux 下为 /)
full_path = os.path.join(base_dir, sub_dir, filename)

print(f"跨平台路径: {full_path}")

输出结果:

三、打开文件

在确定了目标文件的路径后,程序操作文件的第一步是向操作系统申请访问权限并建立通信。在 Python 中,这一过程由内置函数**open()**完成


1. open() 函数

open() 函数的作用是建立程序与磁盘文件之间的映射,并返回一个文件句柄。其最常用的语法结构如下:

python 复制代码
file_object = open(file, mode='r', encoding=None)

- file:目标文件的路径
- mode:指定文件的打开模式,默认为 'rt'(即只读文本模式)
- encoding:指定文本解析所使用的字符编码格式

2. 文件打开模式

根据对文件的操作需求(读取、写入、追加)以及处理的数据类型(文本或二进制),open() 函数提供了多种标志位

基础操作标志

标志 模式 文件存在时的行为 文件不存在时的行为 初始指针位置
r 只读 正常打开,允许读取 抛出 FileNotFoundError 文件开头
w 只写 清空原文件内容(截断) 自动创建新文件 文件开头
a 追加写入 保留原内容,仅允许在末尾追加 自动创建新文件 文件末尾
x 排他性创建 抛出 FileExistsError 自动创建新文件 文件开头

w 模式具备破坏性。一旦使用 open("data.txt", "w") 执行打开操作,无论后续是否写入数据,原文件的内容都会被立即清空。如果不希望覆盖已有数据,应当使用 a 模式或 x 模式

数据形态标志

数据形态标志需与基础操作标志组合使用:

  • t(文本模式,Text Mode)

    • 读写的数据类型为字符串

    • 操作系统会在内存与磁盘交互时,自动将字节流根据指定的字符集解码为文本,或将文本编码为字节流

    • 自动处理不同操作系统的换行符转换

  • b(二进制模式,Binary Mode)

    • 读写的数据类型为字节串

    • 数据以字节形式传输,不进行字符编解码

    • 处理图片、音频、视频或压缩包等非文本文件时,必须显式指定 b 模式

读写扩展标志

  • +(更新模式,Update Mode)

    • 允许同时进行读取和写入操作(如 r+ 表示可读可写,w+ 表示清空重写并可读,a+ 表示追加写入并可读)
复制代码

四、读取文件

当通过 open() 函数成功建立文件句柄后,我们需要将磁盘上的数据读取到内存中。Python 提供了多种读取 API,不同 API 在内存占用与读写性能上存在显著差异


1. read()

read() 方法用于从当前文件指针位置开始读取文件内容

python 复制代码
file.read(size: int = -1) -> str | bytes

size:指定读取的字符数(文本模式)或字节数(二进制模式)
      若不传则读取当前指针位置至文件末尾的所有内容

返回值:在文本模式下返回 str 字符串,在二进制模式下返回 bytes 字节串

内存占用:当不带参数调用时,该方法会将整个文件的内容完全加载至物理内存中,其空间复杂度为 O(N)。若文件尺寸达到 GB 级别,极易引发内存溢出

python 复制代码
# 示范:使用 read() 读取小型配置文件
file_handle = open("config.json", mode="r", encoding="utf-8")
content = file_handle.read()  # 一次性读入内存
file_handle.close()

print(f"读取的数据长度: {len(content)} 字符")

2. readline()

readline() 方法用于从文件中读取单行数据

python 复制代码
file.readline(size: int = -1) -> str | bytes

size:指定单次读取的最大字符数/字节数。若设定了 size 且该数值小于当前行的字符数,
      方法会在读取 size 个字符后提前停止,不再等待换行符。若为 -1,则完整读取整行

返回值:包含当前行数据的 str 或 bytes(末尾保留换行符 \n)
        当到达文件末尾时,返回空字符串或空字节串 

内存占用:每次仅在内存中驻留一行数据,空间开销低

python 复制代码
file_handle = open("server.log", mode="r", encoding="utf-8")

# 逐行读取
while True:
    line = file_handle.readline()
    if not line:  # 遇到空字符串,说明已到达文件末尾
        break
    print(line, end="")

file_handle.close()

3. readlines()

readlines() 方法用于读取文件的所有行,并将它们组合为一个字符串列表返回

python 复制代码
file.readlines(hint: int = -1) -> list[str] | list[bytes]

hint:控制读取的缓冲区字节数。若 hint 大于 0,方法会在读取的行字节数超过 hint 时停止读取
      若为 -1,则读取所有剩余行

返回值:由每一行字符串或字节串构成的列表

内存 :同样属于即时求值。它不仅需要在内存中存下整个文件的文本内容,还需要额外开辟列表空间,内存开销高于 read()

python 复制代码
file_handle = open("users.txt", mode="r", encoding="utf-8")
lines = file_handle.readlines()  # 返回包含所有行字符串的列表
file_handle.close()

# 可以通过列表索引访问特定行
if lines:
    print(f"第一行内容: {lines[0].strip()}")

4. 文件对象遍历

Python 中的文件句柄对象本身是一个可迭代对象。直接对其进行 for 循环遍历,是处理文本文件最为高效的方式

  • 机制

    • 利用缓冲区与惰性求值机制,在后台按需从磁盘拉取数据
  • 内存

    • 空间复杂度为 O(1)。即使面对海量日志文件,程序也不会因内存不足而崩溃
python 复制代码
file_handle = open("large_data.csv", mode="r", encoding="utf-8")

# 最佳实践:直接遍历文件句柄
for line in file_handle:
    # 每次循环仅在内存中加载一行
    if "ERROR" in line:
        print(f"匹配到错误日志: {line.strip()}")

file_handle.close()

5. 读取方式对比与最佳实践

为了在实际工程中进行合理的 API 选型,下表总结了四种读取方式的技术特征:

方法 机制 空间复杂度 内存占用 适用场景
read 将文本全部加载为字符串 O(N) 随文件体积线性增长 小型文本文件
readline 读取单行文本 O(1) 仅占用单行文本内存 需要精准控制读取行数时
readlines 一次性读取全量行并构建 list O(N) 需同时承担全量文本与列表结构的内存开销 中小规模文件且需要进行列表切片或索引访问时
for 惰性读取 O(1) 内存占用恒定 所有通用文本处理场景、海量日志文件分析
  • 处理超大文件时:严禁无参数使用 read() 或 readlines(),应优先选择 for line in file 迭代模式

  • 需要批量读取二进制块时:使用循环配合 read(chunk_size)(例如指定 chunk_size = 4096 字节),按固定分块读取,兼顾 I/O 效率与内存控制

五、关闭文件

在前面的章节中,我们在完成文件读取操作后,均显式调用了 file.close() 方法。但在实际软件工程中,仅依赖手动调用 close() 进行资源回收存在极大的安全隐患

本章将剖析文件资源泄露的底层原因,with 语句与上下文管理


1. 为什么必须关闭文件

当程序通过 open() 打开一个文件时,操作系统会在内核中分配资源。不及时关闭文件会导致以下严重后果:

文件句柄泄露

操作系统对单个进程能够同时打开的文件句柄数量存在上限。如果程序在一个长久运行的服务中频繁打开文件却不关闭,文件句柄将被逐渐耗尽,最终导致操作系统拒绝该进程后续的所有 I/O 请求

数据丢失

为了提高 I/O 吞吐性能,写入文件的数据往往会先暂存在内存缓冲区中。只有在缓冲区填满、程序显式调用 flush() 或调用 close() 时,数据才会被真正刷入磁盘。若程序异常中断且文件未关闭,缓冲区中的数据可能会丢失

占用文件锁

在 Windows 等操作系统中,打开的文件会被施加锁。如果程序没有正确释放文件句柄,其他进程将无法对该文件进行重命名、删除或修改操作


2. close()

如果采用纯手动的 close() 调用,一旦 open() 与 close() 之间的业务代码抛出异常,程序控制流将直接中断,导致 close() 被跳过:

python 复制代码
# 危险代码:若发生异常,f.close() 永远不会被执行
f = open("data.txt", "r", encoding="utf-8")
data = f.read()
result = 1 / 0  # 抛出除0异常,程序中断,文件未关闭
f.close()

在 with 语句出现之前,标准的工程解决思路是利用 try...finally 结构,利用 finally 块 "无论是否发生异常均会强制执行" 的特性保证资源关闭:

python 复制代码
f = open("data.txt", "r", encoding="utf-8")
try:
    data = f.read()
    # 执行业务
finally:
    # 确保文件被可靠关闭
    f.close()

这种写法虽然解决了资源泄露问题,但在处理多个文件嵌套读写时,代码结构会变得非常臃肿


3. with 语句

为了以更加优雅、精简的方式管理资源,Python 引入了 with 语句(又称上下文管理器)

with 语句能在代码块执行完毕或触发任何异常时,自动、隐式地调用资源的清理逻辑

python 复制代码
with open("data.txt", "r", encoding="utf-8") as f:
    data = f.read()
    # 出了这个代码块后,f 会被操作系统自动关闭

即使在 with 代码块内部显式执行了 return、break 或抛出未捕获的异常,with 结构依然能百分之百保证文件资源被安全释放


4. with 语句原理

with 语句能够生效,并非依靠解释器的黑魔法,而是依赖于 Python 的上下文管理器协议

核心魔术方法

任何一个 Python 对象,只要在类内部同时实现了以下两个魔术方法,它就具备了作为 "上下文管理器" 的资格,能够直接配合 with 语句使用:

  1. enter(self):

    • 在进入 with 代码块之前由解释器自动触发

    • 该方法的返回值会通过 as 关键字绑定给指定的变量(例如 open() 返回的 file_object)

  2. exit(self, exc_type, exc_val, exc_tb):

    • 在离开 with 代码块时自动触发

    • 负责执行清理逻辑(例如调用 close() 释放文件句柄)

    • 如果代码块触发了异常,异常的类型、实例和追溯信息会分别作为 exc_type、exc_val 和 exc_tb 参数传递进来

六、写入文件

在理解了文件读取与资源管理后,本章将系统讨论如何向磁盘写入数据。写操作不仅涉及数据格式的转换,更与系统的内存缓冲区机制和模式选择密切相关


1. 基础写入 API

Python 提供了两个核心方法用于向文件对象写入数据:write() 与 writelines()

单次写入:write()

python 复制代码
file.write(text: str | bytes) -> int

text:传入需要写入的字符串或字节串

返回值:返回实际写入文件的字符数或字节数

关键行为:
write() 方法不会在文本末尾追加换行符 \n。如果需要换行,必须在字符串中显式包含
python 复制代码
with open("output.txt", "w", encoding="utf-8") as f:
    chars_written = f.write("Hello, World!\n")
    print(f"实际写入字符数: {chars_written}")

批量写入:writelines()

python 复制代码
file.writelines(lines: Iterable[str | bytes]) -> None

lines:接收一个包含多个字符串或字节串的可迭代对象

关键行为:
不自动拼接分隔符:该方法仅仅是循环调用 write() 将列表中的元素依次写入
不会自动在各个元素之间添加换行符或空格
python 复制代码
lines = ["第一行数据\n", "第二行数据\n", "第三行数据\n"]

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

2. flush()

在操作系统底层,频繁向磁盘写入微小的数据块会引发巨大的 I/O 开销。为了优化吞吐性能,Python 配合操作系统实现了缓冲区机制

数据的传输路径

python 复制代码
应用程序 write() ───► 内存缓冲区 (Buffer) ───► 操作系统内核页缓存 ───► 物理磁盘

当执行 file.write() 时,数据并未立刻写入物理磁盘,而是存放在内存缓冲区中。数据真正落盘的触发时机包括:

  1. 缓冲区空间被填满

  2. 文件被显式或隐式调用 close()

  3. 应用程序显式调用 file.flush()

flush() 方法的作用

复制代码
file.flush() -> None

flush() 方法用于强行刷新,清空内存缓冲区,将当前积压的数据立即写入磁盘,但保持文件句柄处于打开状态

七、目录操作

在实际软件开发中,程序很少单独处理文件。文件通常按照一定的层级结构组织在目录中

需要明确的是,Python 中处理目录和文件系统属性的核心工具主要分布在标准库os 与 os.path 模块中。本章将完全基于这两个经典模块展开讲解


1. 当前工作目录

程序在解析相对路径时,其基准点永远是当前工作目录

获取当前工作目录:os.getcwd()

python 复制代码
import os

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

切换当前工作目录:os.chdir(path)

通过 os.chdir() 可以动态改变当前进程的工作目录。如果传入的路径不存在,会抛出 FileNotFoundError 异常

python 复制代码
import os

try:
    os.chdir("./data")  # 切换到子目录 data
    print(f"切换后的工作目录: {os.getcwd()}")
except FileNotFoundError as e:
    print(f"切换失败,目标路径不存在: {e}")

2. 路径状态判断

在进行文件的读写或目录创建前,进行路径检查是编写稳健代码的关键环节。os.path 模块提供了丰富的判断与状态获取工具:

签名 返回值 功能
exists(path) bool 判断指定的路径(文件或目录)在系统中是否存在
isfile(path) bool 判断指定路径是否存在且为一个常规文件
isdir(path) bool 判断指定路径是否存在且为一个目录
isabs(path) bool 判断指定的路径字符串是否为绝对路径
getsize(path) int 获取文件的字节大小(若是目录,返回系统分配的元数据大小)
getmtime(path) float 获取文件或目录的最后修改时间
python 复制代码
import os
import time

target_path = "config.json"

if os.path.exists(target_path):
    if os.path.isfile(target_path):
        size = os.path.getsize(target_path)
        mtime = os.path.getmtime(target_path)
        formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(mtime))
        print(f"文件大小: {size} 字节")
        print(f"最后修改时间: {formatted_time}")
else:
    print("目标文件不存在。")

3. 目录与文件的创建、删除及重命名

创建目录:os.mkdir() 与 os.makedirs()

  • os.mkdir(path): 用于创建单层目录。如果父级目录不存在,会抛出 FileNotFoundError;如果目标目录已存在,会抛出 FileExistsError

  • os.makedirs(name, exist_ok=False): 用于递归创建多层深层目录

    • 参数 exist_ok=True 表示如果目标目录已存在,则静默忽略而不抛出异常
python 复制代码
import os

# 1. 创建单级目录
if not os.path.exists("logs"):
    os.mkdir("logs")

# 2. 递归创建多级嵌套目录(推荐做法)
os.makedirs("data/2026/07", exist_ok=True)

删除文件与目录

  • os.remove(path) / os.unlink(path): 专门用于删除单一文件。若传入目录路径,会抛出 IsADirectoryError

  • os.rmdir(path): 专门用于删除单一空目录。如果目录非空,会抛出 OSError

  • os.removedirs(name): 递归尝试删除多级空目录

python 复制代码
import os

# 安全删除文件示范
file_to_delete = "temp.log"
if os.path.isfile(file_to_delete):
    os.remove(file_to_delete)

# 安全删除空目录示范
dir_to_delete = "empty_folder"
if os.path.isdir(dir_to_delete):
    try:
        os.rmdir(dir_to_delete)
    except OSError:
        print("删除失败:目标目录非空。")

注意:如果需要强制递归删除包含内容的非空目录树,标准库 os 本身不提供直接接口,应使用标准库 shutil 中的 shutil.rmtree(path)

重命名与移动:os.rename() 与 os.renames()

os.rename(src, dst) 用于重命名文件或目录

python 复制代码
import os

# 将 old_name.txt 重命名为 new_name.txt
if os.path.exists("old_name.txt"):
    os.rename("old_name.txt", "new_name.txt")

4. 遍历目录

在批量数据处理、日志分析等任务中,扫描目录树是高频需求。Python 提供了浅层与深层两种遍历机制

浅层遍历:os.listdir(path)

os.listdir() 返回指定目录下所有文件和子目录名称的列表(仅包含名称,不包含完整路径,且不递归深入子目录)

python 复制代码
import os

target_dir = "."
# 获取指定目录下的所有项
items = os.listdir(target_dir)

for item in items:
    # 拼接获取完整路径以进行类型判断
    full_path = os.path.join(target_dir, item)
    item_type = "目录" if os.path.isdir(full_path) else "文件"
    print(f"[{item_type}] {item}")

深层递归遍历:os.walk(top, topdown=True)

os.walk() 是一个强大的生成器函数,用于自顶向下或自底向上递归遍历整个目录树

返回值:每次迭代都会产出一个包含 3 个元素的元组 (dirpath, dirnames, filenames):

  1. dirpath(字符串):当前正在遍历的目录路径

  2. dirnames (列表):当前目录下的所有子目录名称列表

  3. filenames (列表):当前目录下的所有非目录文件名列表

python 复制代码
import os

project_root = "./my_project"

# 递归扫描整个项目目录下的所有文件
for root, dirs, files in os.walk(project_root):
    print(f"\n当前目录位置: {root}")
    
    # 输出当前目录下的所有子目录
    for sub_dir in dirs:
        print(f"子目录: {sub_dir}")
        
    # 输出当前目录下的所有文件
    for file_name in files:
        full_file_path = os.path.join(root, file_name)
        file_size = os.path.getsize(full_file_path)
        print(f"文件: {file_name} ({file_size} 字节)")

为了清晰拆解 os.walk() 的执行,假设我们有如下所示的 my_project 项目目录结构:

python 复制代码
my_project/
├── config.json        
├── main.py           
└── data/
    └── users.csv

当代码运行在该目录结构上时,os.walk() 生成器会触发 2 轮迭代。下表还原了每轮循环中变量的具体数值与代码的执行逻辑:

遍历轮次 root dirs files
第 1 轮 ./my_project 'data' 'config.json', 'main.py'
第 2 轮 ./my_project/data \[\] 'users.csv'

os.walk() 的底层生成器设计,使得遍历包含数百万个文件的巨型目录树时,内存开销始终保持低水平,避免了一次性加载整个树节点所带来的性能衰减

总结

本章学习了 Python 中文件与目录操作的基本方法,了解了文本文件与二进制文件的区别、绝对路径与相对路径的使用方式,以及文件读写的标准流程。我们掌握了 read()、readline()、readlines() 和文件对象遍历等多种读取方式,学习了 with 语句及其背后的 enterexit 工作机制,并熟悉了不同文件打开模式、flush() 方法以及常见的目录操作。最后,通过文件复制和日志记录等案例,将文件操作的相关知识应用到实际开发中。

下一篇文章我们将学习Python 多线程编程,了解线程的基本概念、线程创建与管理、线程同步以及线程安全等内容,为开发高并发程序打下基础

相关推荐
Roy_Sashulin7 小时前
灵杉Java编程平台第一章:安装
java·开发语言
名字还没想好☜7 小时前
Go 用 errgroup 管理并发子任务:错误收敛、取消传播与限流
开发语言·后端·golang·go·并发
xcLeigh7 小时前
Doubao-Seed-Evolving大模型接入教程|搭建全品类提示词+AI工具导航网页
前端·人工智能·python·ai·html·ai开发·豆包
不如语冰7 小时前
AI大模型入门-模块导入import
数据结构·人工智能·pytorch·python
投票竞赛7 小时前
书法、绘画作品投票评选,图片投票小程序作品集排版
python·小程序
梦远青城7 小时前
Docker 部署python的paddle进行OCR文字识别身份证
python·docker·ocr·paddle·身份证识别
2zcode7 小时前
基于MATLAB深度卷积特征的多曝光图像自适应融合系统设计与实现
开发语言·matlab·多曝光图像自适应融合系统
编码者卢布8 小时前
【Azure APIM】APIM的诊断日志与Application Insights的日志是否可以串联为一个端到端的日志链路呢?
python·flask·azure
hold?fish:palm8 小时前
7 接雨水
开发语言·c++·leetcode