python -m和python [file]之间的包加载有什么区别?

问题描述

运行python -m moduala.testpython moduala/testa.py之类的东西时,我在python3中看到了不同的包处理行为。在-m情况下,在testa.py中对moduala.modualb.pkgx的导入有效,而在其他情况下,它们则无效。

python --version
# Python 3.6.9

mkdir -p testpyproj/pkga/pkgb
cd testpyproj/

touch pkga/__init__.py
touch pkga/pkgb/__init__.py

echo 'print("# python!")' >pkga/pkgb/modx.py
echo 'from pkga.pkgb import modx' > pkga/test.py

python -m pkga.test
# python!

python pkga/test.py 
# Traceback (most recent call last):
#  File "pkga/test.py",line 1,in <module>
#     from pkga.pkgb import modx
# ImportError: No module named pkga.pkgb

在手册页中,我希望它们是相同的:

  -m module-name
         Searches sys.path for the named module and 
         runs the corresponding .py file as a script.

python -m和python [file]在加载模块和处理软件包之间有什么区别?

为什么python [file]找不到pkga.pkgb?

解决方法

当python从命令行运行脚本时,例如:

$ python pkga/test.py

知道它正在运行一个相对的脚本。因此,它会将sys.path[0]的值更改为脚本的目录。strong>

当python从命令行打开模块时,它必须具有模块搜索路径(aka sys.path)才能找到该模块。因此,它将sys.path[0]设置为""(空字符串)以表示“当前目录”。然后,它搜索sys.path所指示的所有位置,以查找您给定的模块名称。

其结果是,在一种情况下,您的sys.path[0]将是"",而在另一种情况下,它将是/path/to/current/directory/pkga。然后,当搜索路径从该位置开始时,它就无法解析pkga.pkgb

您可以通过添加以下内容来确认这一点:

import sys
print(sys.path)

pkga/test.py的开头,在任何其他导入之前。您将在模块导入异常之前看到打印输出。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...