Python中如何获取被主脚本调用的子脚本所在目录?
解决子脚本调用自定义包函数时获取自身目录的问题
这个问题的核心在于你需要获取的是调用该包函数的脚本路径,而非包本身或主脚本的路径。之前的尝试要么依赖进程的工作目录(os.getcwd()),要么只获取了包的帧信息,我们可以通过调整inspect的栈帧层级来解决。
核心解决方案:获取调用者的脚本路径
修改你自定义包中的函数,让它获取调用该函数的代码所在的栈帧,而不是函数自身的帧。这样不管是主脚本、exec执行的子脚本还是subprocess启动的子脚本调用它,都能拿到正确的调用者目录。
# 自定义包中的函数 import os import inspect def get_caller_script_dir(): # 获取当前函数的上一层栈帧(即调用该函数的代码所在的帧) caller_frame = inspect.currentframe().f_back if not caller_frame: # 极端情况:没有调用帧, fallback到当前工作目录 return os.getcwd() # 获取调用者的脚本文件名 caller_filename = inspect.getframeinfo(caller_frame).filename # 返回该脚本的目录 return os.path.dirname(os.path.abspath(caller_filename))
针对不同调用场景的细节处理
1. 使用exec执行子脚本的情况
exec默认会在主脚本的上下文执行,子脚本的__file__不会被自动设置。你需要在exec时手动注入__file__变量,确保子脚本的代码能正确暴露自己的路径:
# 主脚本中exec子脚本的代码 import os sub_script_path = "./path/to/your/sub_script.py" with open(sub_script_path, 'r') as f: # 编译子脚本代码,指定文件名(用于inspect识别) code = compile(f.read(), sub_script_path, 'exec') # 注入__file__变量到执行上下文 exec(code, {"__file__": sub_script_path})
此时子脚本调用get_caller_script_dir()时,就能拿到子脚本自身的目录。
2. 使用subprocess调用子脚本的情况
如果之前用subprocess遇到问题,大概率是因为子脚本没有正确导入你的自定义包,或者你没有以独立进程的方式启动它。确保:
- 子脚本能正确找到自定义包(比如把包所在目录加入
sys.path,或者安装为可导入的包) - 使用完整的Python命令启动子脚本,让它作为独立进程运行:
# 主脚本中subprocess调用的代码 import subprocess sub_script_path = "./path/to/your/sub_script.py" # 启动独立进程执行子脚本 subprocess.run(["python", sub_script_path], check=True)
此时子脚本中的__file__会自动指向自身路径,调用get_caller_script_dir()就能拿到正确的目录。
为什么之前的尝试没成功?
os.getcwd():返回的是进程的工作目录,exec和默认的subprocess都会继承主脚本的工作目录,所以拿到的是主脚本目录。- 直接用
inspect.currentframe():拿到的是包函数自身的栈帧,所以返回的是包的路径;而我们需要往上找一层,获取调用者的帧。
内容的提问来源于stack exchange,提问作者AJT
相关产品推荐
相关产品推荐

