如何让Python模块导入在直接运行或被父模块导入时均生效?
解决Python模块导入的跨场景兼容问题
项目结构
pkg\ main.py __init__.py subpkg\ foo.py bar.py __init__.py
原代码问题
foo.py原代码:
from bar import baz def something_intended_to_be_called_from_main(): baz() def quick_and_dirty_tests_while_programming(): pass if __name__ == '__main__': quick_and_dirty_tests_while_programming()
main.py代码:
import subpkg.foo
直接运行foo.py时,from bar import baz能正常解析;但运行main.py时,这条导入会失败,因为Python在pkg目录下找不到bar模块。如果改成from subpkg.bar import baz,直接运行foo.py时又会因为找不到subpkg包而报错。
优雅解决方案
方案1:使用相对导入 + 模块方式运行
修改foo.py的导入语句为相对导入:
from .bar import baz def something_intended_to_be_called_from_main(): baz() def quick_and_dirty_tests_while_programming(): pass if __name__ == '__main__': quick_and_dirty_tests_while_programming()
之后直接运行foo.py时,不要用python subpkg/foo.py这种脚本方式运行,而是切换到pkg所在的上级目录,用模块方式运行:
python -m pkg.subpkg.foo
这种方式下:
- 当main.py导入subpkg.foo时,相对导入
from .bar import baz会正确定位到同目录下的bar模块; - 用
python -m命令运行时,Python会将foo视为pkg.subpkg下的模块,相对导入同样有效,测试代码也能正常执行。
方案2:统一使用绝对导入 + 配置PYTHONPATH
如果偏好绝对导入,可将foo.py的导入改为:
from subpkg.bar import baz
然后在运行foo.py前,将项目根目录(pkg的父目录)添加到PYTHONPATH环境变量中:
- Linux/macOS:
export PYTHONPATH=/path/to/pkg-parent-directory:$PYTHONPATH python /path/to/pkg/subpkg/foo.py
- Windows(命令提示符):
set PYTHONPATH=C:\path\to\pkg-parent-directory;%PYTHONPATH% python C:\path\to\pkg\subpkg\foo.py
这样无论是运行main.py还是直接运行foo.py,Python都能通过PYTHONPATH找到subpkg包,绝对导入就能正常解析。
内容的提问来源于stack exchange,提问作者Luke Sawczak
相关产品推荐
相关产品推荐

