前言
我正在开发一个项目,该项目实际上是可以通过pip安装的Python程序包,但是它还提供了命令行界面。使用安装了项目后pip install .
,我的项目运行没有问题,但是,在更改了一个项目文件中的某些内容后,每次由谁来执行此操作?我需要通过简单的操作来完成整个工作python mypackage/main.py
。
/my-project
- README.md
- setup.py
/mypackage
- __init__.py
- main.py
- common.py
相同问题的不同面孔
我尝试main.py
从common.py
模块中导入一些功能。我尝试了不同的配置,这些配置会产生不同的错误,并且我想与您分享我的观察结果,并为将来我留下快速笔记。
相对进口
我首先尝试的是相对导入:
from .common import my_func
我跑我的应用程序简单:python mypackage/main.py
。不幸的是,这产生了以下错误:
ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package
造成此问题的原因是,该命令main.py
直接由python
命令执行,因此成为名为的主模块__main__
。如果将这些信息与我们使用的相对导入相关联,则会得到错误消息中的内容:__main__.common
。在Python文档中对此进行了解释:
请注意,相对导入基于当前模块的名称。由于主模块的名称始终为__main__
,因此打算用作Python应用程序主模块的模块必须始终使用绝对导入。
当我安装软件包pip install .
并运行它时,它运行良好。我还能够mypackage.main
在Python控制台中导入模块。因此,看起来只有直接运行它才有问题。
绝对进口
让我们遵循文档中的建议,并将import语句更改为其他内容:
from common import my_func
如果现在尝试像以前一样运行此命令python mypackage/main.py
,则它可以按预期运行!但是,当您像我一样在使用pip安装它之后开发出一些需要作为独立命令行工具工作的东西时,有一点需要注意。我安装了软件包,pip install .
然后尝试运行它...
ModuleNotFoundError: No module named 'common'
更糟糕的是,当我打开Python控制台并尝试main
手动导入模块(import mypackage.main
)时,出现了与上述相同的错误。原因很简单:common
不再是相对导入,因此Python尝试在已安装的软件包中找到它。我们没有这样的软件包,这就是为什么它失败了。
仅当您创建使用python
命令执行的典型Python应用程序时,使用绝对导入的解决方案才能很好地工作。
使用包名称导入
还有导入common
模块的第三种可能性:
from mypackage.common import my_func
只要我们是根据的上下文,这与相对导入方法并没有太大不同mypackage
。再一次,尝试以python mypackage/main.py
类似的结尾运行此命令:
ModuleNotFoundError: No module named 'mypackage'
解释器很正确,您没有安装这样的软件包,这可能会很令人讨厌。
解决方案
对于简单的Python应用程序
只需使用绝对导入(不带点),一切都会好起来的。
对于开发中的可安装Python应用程序
请使用相对导入,或使用开头带有包名的导入,因为在安装应用程序时,您需要这样的导入。在开发中运行此类模块时,可以使用以下-m
选项执行Python :
-m mod : run library module as a script (terminates option list)
因此python mypackage/main.py
,请改为这样做:python -m mypackage.main
。