Python3.x中os.chdir搭配os.listdir与os.scandir行为差异原因
核心原理说明
1. os.listdir 运行不符合预期的原因
os.listdir的循环并没有提前终止,只是后续分支判断全部失败,没有输出而已,具体逻辑如下:
os.listdir(path)会一次性返回目标路径下所有条目的纯文件名相对路径字符串列表,遍历过程中这个列表是固定不变的。os.path.isdir()传入相对路径字符串时,会基于操作系统当前工作目录(cwd)做路径解析:- 第一次循环时,当前工作目录还是你传入的初始路径
D:/python-venvs/pyinst,此时匹配到第一个子目录名,判断为真,执行os.chdir(item)后,工作目录切换为D:/python-venvs/pyinst/1.3.1.2-modules。 - 后续循环拿到的还是初始路径下的子目录名,此时判断路径会变成
D:/python-venvs/pyinst/1.3.1.2-modules/[子目录名],这个路径不存在,所以if分支不会触发,看起来就像循环提前终止。
- 第一次循环时,当前工作目录还是你传入的初始路径
2. os.scandir 运行正常的原因
os.scandir返回的DirEntry对象自带初始路径上下文,不依赖当前工作目录:
- 调用
os.path.isdir(item)时,直接读取DirEntry内置的文件类型缓存,判断的是初始路径下对应条目的类型,和当前工作目录无关,所有子目录的判断都会成功。 - 执行
os.chdir(item)时,Python会自动调用DirEntry的__fspath__方法返回该条目的完整绝对路径,不管当前工作目录在哪,都会直接切换到对应子目录的绝对路径,所以每次切换都能成功。
通用规避方案
如果要避免这类路径依赖问题,推荐两种通用写法:
- 所有路径操作统一使用绝对路径:用
os.path.join(path, item)拼接成完整路径后再做判断、切换操作。 - 切换目录后及时复位:进入子目录完成操作后立刻执行
os.chdir("..")回到上级目录,保证后续相对路径判断逻辑正常。
内容的提问来源于stack exchange,提问作者bhagerty
相关产品推荐
相关产品推荐

