将Python项目打包后,如何自动为所有导入添加包前缀?
Python打包后短导入报错的快速解决方法
问题根源
开发时你在内层project_name目录运行脚本,该目录会被自动加入Python的sys.path,因此sub_module被视为顶层模块,可直接用短导入;但打包安装后,只有外层定义的project_name是顶层包,sub_module是它的子模块,直接导入会触发ModuleNotFoundError。
无需修改代码的解决方法
方法1:调整setup.py的包配置
修改setup.py,将sub_module注册为顶层模块,同时指向其实际所在路径:
from setuptools import setup, find_packages setup( name="project_name", version="0.1.0", # 同时包含主包和要暴露的子模块 packages=find_packages() + ["sub_module"], # 指定sub_module的实际位置 package_dir={"sub_module": "project_name/sub_module"}, # 其他必要配置(如author、description等) )
打包安装后,sub_module会被识别为顶层模块,原有的短导入语句无需修改即可正常运行。
方法2:用pyproject.toml配置(推荐)
如果使用现代Python打包规范(pyproject.toml),可以这样配置:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "project_name" version = "0.1.0" [tool.setuptools.packages.find] where = ["."] include = ["project_name*", "sub_module*"] [tool.setuptools.package-dir] sub_module = "project_name/sub_module"
效果和方法1一致,更符合当前Python打包的最佳实践。
额外提示(规范开发方式)
如果不想依赖打包配置的hack,建议开发时在外层目录运行脚本,用python -m project_name.your_script的方式启动,同时代码中使用相对导入:
from .sub_module.file_containing_class import SomeClass
这种方式无需修改打包配置,也能保证开发和生产环境的导入一致性,是更规范的做法。
内容的提问来源于stack exchange,提问作者foobar_98
相关产品推荐
相关产品推荐

