os.walk与glob.glob返回结果不一致的技术咨询
os.walk与glob.glob查找Python文件的差异原因
核心差异:隐藏目录的匹配规则
- glob.glob的默认行为
Python的glob模块默认会忽略以.开头的文件和目录(即系统定义的隐藏文件/目录),除非匹配模式中明确包含.。当使用**/*.py并设置recursive=True时,**不会遍历名称以.开头的子目录(比如.venv),因此这些目录下的.py文件不会被匹配到——这就是你用glob找不到.venv路径下pyparsing.py的原因。
而名称不以.开头的目录(比如venv)不在glob的忽略范围内,**会正常遍历这类目录,所以glob能找到其中的.py文件。
- os.walk的遍历逻辑
os.walk会遍历指定根目录下的所有子目录,不管目录名称是否以.开头,也不会默认忽略任何目录(除非你手动修改dirnames列表排除目录)。因此它能正常找到.venv目录下的.py文件。
为什么os.walk没找到部分venv下的文件?
你提到os.walk未返回部分含/venv/的文件,可能的原因包括:
- 部分
venv目录是符号链接:os.walk默认参数followlinks=False,不会跟随符号链接目录;而glob.glob在recursive=True时会跟随符号链接(取决于系统和Python版本),导致这部分文件只被glob捕获。 - 代码缩进错误:你提供的os.walk代码中,
for循环前有多余缩进,这会引发语法错误。如果实际运行的代码存在类似问题,可能导致部分目录未被遍历。 - 系统权限限制:部分
venv目录下的文件可能存在权限问题,os.walk无法访问,而glob在遍历过程中的权限处理逻辑不同,跳过了这类限制。
统一结果的解决方案
如果想让两种方法返回一致的结果,可以做以下调整:
- 让glob匹配隐藏目录:Python 3.13+版本新增了
include_hidden参数,开启后可匹配隐藏目录:repos_path = f"{os.path.dirname(__file__)}/repos" pyfiles = glob.glob(f"{repos_path}/**/*.py", recursive=True, include_hidden=True) - 让os.walk排除指定目录:在遍历过程中手动移除不需要的目录,避免无效遍历:
abs_paths = [] repos_path = f"{os.path.dirname(__file__)}/repos" for dirpath, dirnames, filenames in os.walk(repos_path): # 移除venv和.venv目录,不遍历其下内容 dirnames[:] = [d for d in dirnames if d not in ('venv', '.venv')] for f in filenames: abs_path = os.path.join(dirpath, f) if abs_path.endswith(".py"): abs_paths.append(abs_path)
内容的提问来源于stack exchange,提问作者MPP
相关产品推荐
相关产品推荐

