如何判断pathlib.Path对象是否为另一个路径的子目录?
判断pathlib.Path是否为另一个路径的子目录
Python 3.9+ 推荐用法
pathlib.Path和PurePath从Python 3.9开始内置了**is_relative_to()**方法,能精准判断一个路径是否是另一个路径的子路径(或路径本身),完全规避字符串匹配的漏洞:
from pathlib import Path root_dir = Path("/home/user/projects") sub_dir = Path("/home/user/projects/utils") unrelated_dir = Path("/home/user/downloads") print(sub_dir.is_relative_to(root_dir)) # 输出 True print(unrelated_dir.is_relative_to(root_dir)) # 输出 False
兼容Python 3.8及以下版本
如果你的环境是旧版Python,可以通过解析路径的父节点列表来判断:
from pathlib import Path def is_subpath(child_path: Path, parent_path: Path) -> bool: # 先标准化路径,消除相对路径符号 child = child_path.resolve() parent = parent_path.resolve() # 检查父路径是否在子路径的所有父节点中,或两者路径完全相同 return parent in child.parents or child == parent root_dir = Path("/home/user/projects") sub_dir = Path("/home/user/projects/utils") print(is_subpath(sub_dir, root_dir)) # 输出 True
修复你提供的压缩文件代码
你原来用字符串包含的判断逻辑存在误判风险(比如路径名称部分重叠时会出错),下面用is_relative_to()替换原有逻辑,优化后的代码如下:
import zipfile import pathlib import os import logging log = logging.getLogger(__name__) with zipfile.ZipFile(fname, 'w') as zip: for f in files: myrelroot = relroot # 当前压缩包的相对根路径 try: f_path = pathlib.Path(f) relroot_path = pathlib.Path(relroot) # 判断当前文件是否在指定根路径范围内 if not f_path.is_relative_to(relroot_path): myrelroot = None # 不在范围内,避免生成../这类不安全路径 except ValueError: # 路径格式不合法时也设为None myrelroot = None try: if myrelroot: arcname = os.path.relpath(f, myrelroot) else: # 不在范围内时,直接使用文件名作为归档名(可按需调整) arcname = pathlib.Path(f).name zip.write(f, arcname=arcname) except FileNotFoundError as e: log.warning(f"文件 '{f}' 未找到: {e}") else: log.info(f"正在将 {f} 添加到 {fname}")
字符串匹配的问题
假设你的根路径是/data/report,而某个文件路径是/data/report_card/file.csv,字符串匹配会错误地认为该文件在根路径范围内,但实际上两者毫无关系。is_relative_to()方法会基于路径的层级结构判断,不会出现这类误判。
内容的提问来源于stack exchange,提问作者MortenB
相关产品推荐
相关产品推荐

