Python代码相对路径使用最佳实践:跨目录传路径问题解决方案
Python跨模块路径引用最佳实践
核心原则
不需要强制写死绝对路径,核心要做到统一路径锚点:要么传递已经解析完成的绝对路径对象,要么约定所有相对路径都基于同一个固定锚点(通常是项目根目录)计算,禁止跨模块传递基于单个文件所在目录的相对路径。
方案1:调用方提前解析为绝对路径(最稳妥,无歧义)
你遇到的问题本质是把基于module1/app.py的相对路径字符串传给了utils模块,utils模块计算路径的基准目录和app.py不一致,导致路径出错。你可以在调用方直接把路径解析为完整的绝对路径对象再传递,utils不需要关心路径的来源,直接使用即可。
示例代码
src/module1/app.py 写法:
from pathlib import Path from utils.utils import process_pdf # 锚定到项目根目录:从app.py所在目录(module1)往上跳3级,到达project根目录 PROJECT_ROOT = Path(__file__).parent.parent.parent # 直接拼接得到目标文件的完整绝对路径 target_file = PROJECT_ROOT / "data" / "raw" / "test.pdf" # 传递Path对象给utils的函数,不需要传相对路径字符串 result = process_pdf(target_file)
src/utils/utils.py 写法:
from pathlib import Path def process_pdf(file_path: Path): # 直接使用传入的路径对象,不需要二次拼接,完全无歧义 with open(file_path, "rb") as f: # 你的文件处理逻辑 return f.read()
该方案的优势是utils层的函数完全和路径逻辑解耦,复用性更高,不管调用方来自哪个模块、传什么位置的路径都可以正常处理。
方案2:统一以项目根目录为唯一锚点(适合多路径调用场景)
如果你的项目需要大量传递路径字符串,可以约定所有传入的相对路径默认基于项目根目录计算,在utils层统一封装路径解析逻辑,不需要每个调用方自己拼接路径。
示例代码
首先在utils层封装定位项目根目录的公共函数:src/utils/utils.py 写法:
from pathlib import Path def get_project_root() -> Path: # 从当前文件所在目录往上查找,直到找到包含src文件夹的目录即为项目根 current_dir = Path(__file__).parent while not (current_dir / "src").exists(): current_dir = current_dir.parent # 遍历到根目录还没找到,抛出异常 if current_dir == Path("/"): raise RuntimeError("未识别到项目根目录,请确认项目结构是否符合预期") return current_dir def process_pdf(relative_path: str): project_root = get_project_root() full_path = project_root / relative_path with open(full_path, "rb") as f: return f.read()
src/module1/app.py 写法:
from utils.utils import process_pdf # 直接传入相对于项目根目录的路径字符串即可 result = process_pdf("data/raw/test.pdf")
该方案的优势是调用方不需要关心路径拼接逻辑,传参更简洁,适合有大量路径调用的项目。
注意事项
- 尽量使用
pathlib.Path对象传递路径,自动适配不同操作系统的路径分隔符,避免手动拼接字符串出错 - 不要跨模块传递基于单个文件所在目录的相对路径,每个模块的
__file__基准目录不同,极易出现路径错位问题 - 生产环境也可以将项目根目录配置到系统环境变量中,读取环境变量定位根目录,灵活性更高
内容的提问来源于stack exchange,提问作者Steve Nathan
相关产品推荐
相关产品推荐

