主脚本如何从文件系统上级目录导入模块(禁止from后加圆点)
解决file2.py作为主脚本时导入pkg_1中Klass的问题
先明确你的项目结构:
prj/ ├── pkg_1/ │ └── file1.py # 内含Klass类 └── pkg_2/ └── file2.py # 我们要处理的目标脚本
当file2.py作为主脚本直接运行时(比如执行python pkg_2/file2.py),Python默认会把pkg_2目录加入模块查找路径sys.path,但pkg_1在它的上级目录prj里,直接写from pkg_1.file1 import Klass会找不到模块。下面给你两种靠谱的解决办法,完全符合你「不能用带圆点的相对导入」的要求:
方法1:动态修改sys.path(适配所有运行场景)
在file2.py的主脚本逻辑里,借助os模块动态获取prj根目录并加入Python的模块查找路径,这样不管你在哪运行脚本都能生效:
# 您现在位于名为`file2.py`的文件中 import sys import os if __name__ == '__main__': # 获取当前脚本所在的绝对目录(也就是pkg_2) current_dir = os.path.dirname(os.path.abspath(__file__)) # 往上回溯一级,得到prj根目录 prj_root = os.path.dirname(current_dir) # 将prj目录加入sys.path,让Python能找到pkg_1包 sys.path.append(prj_root) # 现在可以直接用绝对导入 from pkg_1.file1 import Klass # 这里可以添加主脚本的业务逻辑,比如实例化Klass klass_instance = Klass() else: # 当前并非主脚本 from ..pkg_1.file1 import Klass
这种方法的优势是灵活性拉满,不管你是进入pkg_2目录直接运行脚本,还是在prj目录下执行,都能正常导入模块。
方法2:用-m参数以模块方式运行(更规范,推荐生产场景)
如果你能控制脚本的启动方式,可以从prj目录出发,用Python的模块运行命令启动file2.py:
cd prj python -m pkg_2.file2
这时候Python会自动把prj目录加入sys.path,你不需要修改路径,直接写绝对导入即可:
# 您现在位于名为`file2.py`的文件中 if __name__ == '__main__': # 直接使用绝对导入,prj目录已被Python自动加入查找路径 from pkg_1.file1 import Klass else: # 当前并非主脚本 from ..pkg_1.file1 import Klass
这种方式更符合Python的包管理规范,避免手动修改sys.path的潜在问题,但缺点是必须从prj目录用-m参数启动,不能直接双击或用python file2.py启动脚本。
补充说明
为什么主脚本不能用相对导入?因为当脚本作为主模块运行时,Python会将其视为「顶层脚本」,这时候带.或..的相对导入是不被允许的,所以必须通过绝对导入的方式解决——要么手动把父目录加入查找路径,要么通过-m参数让Python自动处理路径。
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

