Python脚本从上级目录common导入模块可行吗?需__init__.py吗?
好问题!咱们直接说重点:
1. 直接用from ../../common/ import <python_file>可行吗?
不行。Python的导入系统不支持这种文件路径式的写法——相对导入的语法是用.表示当前目录,..表示上级目录,但有个前提:你的脚本不能是直接作为__main__模块运行的(也就是不能直接python your_script.py)。而你的场景是大量可直接运行的脚本,所以这种写法直接用会报错。
2. 需要__init__.py吗?
在Python 3.3及以上版本,不需要。从3.3开始,Python引入了「命名空间包」,即使目录里没有__init__.py,也会被视为一个可导入的包。不过如果你的common目录需要做一些初始化操作,或者想统一导出内部模块的内容,加个__init__.py会更方便(比如在里面写from . import utils,这样外面可以直接from common import utils),但这不是必须的。
3. 最简单的实现方法(无需复杂操作)
最直接的办法是在脚本开头临时把项目根目录添加到Python的搜索路径sys.path里,代码非常简单:
import sys from pathlib import Path # 拿到当前脚本的绝对路径,然后往上跳3级到项目根目录(根据你的目录结构调整层级) # 比如你的脚本在根目录下的 `sub1/sub2/script.py`,那么 parent.parent.parent 就是根目录 project_root = Path(__file__).resolve().parent.parent.parent sys.path.append(str(project_root)) # 现在就能正常导入了 from common import your_python_file
如果不确定层级,也可以用更通用的写法,直接定位到common目录的父目录(也就是项目根):
project_root = Path(__file__).resolve().parents[2] # 数字2表示往上跳2级,根据实际情况调整 sys.path.append(str(project_root))
这样修改后,你直接运行脚本就能成功导入common里的模块了,完全不需要复杂的配置。
补充:另一种相对导入的方式(适合模块式运行)
如果你愿意把脚本当作模块来运行(而不是直接执行),可以用Python的-m参数,比如你的脚本在project_root/sub1/sub2/script.py,那么在项目根目录下运行:
python -m sub1.sub2.script
这时候脚本是作为模块被加载的,你就可以用相对导入:
from ...common import your_python_file
不过这种方式需要你每次都从项目根目录用-m运行,对直接双击脚本的场景不太友好,所以还是第一种方法更适合你的需求。
内容的提问来源于stack exchange,提问作者deficiencyOn

