假设我有以下文件,
pkg/ pkg/__init__.py pkg/main.py # import string pkg/string.py # print("Package's string module imported")
现在,如果我跑步main.py,它说"Package's string module imported"。
main.py
"Package's string module imported"
这是有道理的,并且按照此链接中的以下语句运行:
“它将首先在包的目录中查找”
假设我稍微修改了文件结构(添加了一个核心目录):
pkg/ pkg/__init__.py plg/core/__init__.py pkg/core/main.py # import string pkg/string.py # print("Package's string module imported")
现在,如果我运行python core/main.py,它将加载内置string模块。
python core/main.py
string
同样在第二种情况下,如果必须遵守“ 它将首先在软件包的目录中查找 ” 这样 的语句 ,是否 应该加载本地文件,string.py因为pkg它是“软件包的目录”?
string.py
pkg
我的术语“包目录”的意义是 明确 的 根文件夹 一个的 集合 与文件夹__init__.py。因此,在这种情况下, pkg 是“程序包目录”。它适用main.py于子目录,也适用于子目录中的文件,例如,core/main.py因为它是此“包”的一部分。
__init__.py
core/main.py
这在技术上正确吗?
PS:#代码段后面的内容是文件的实际内容(没有前导空格)。
#
软件包是带有__init__.py文件的目录,是的,并且 在模块搜索路径上找到时 作为模块加载。所以pkg只有一个包,你可以导入和处理作为一个整体 ,如果父目录是模块搜索路径上 。
但是通过将pkg/core/main.py文件作为 脚本 运行,Python将pkg/core目录添加到了模块搜索路径,而不是的父目录pkg。__init__.py现在,您的模块搜索路径上确实有一个文件,但这不是定义包的原因。您只有一个__main__模块,没有其他任何包关系,并且您不能依赖隐式相对导入。
pkg/core/main.py
pkg/core
__main__
您有三种选择:
不要将包中的文件作为脚本运行。将脚本文件 放在 包 之外 ,并根据需要导入脚本。你可以把它 旁边 的pkg目录,或者确保pkg目录首次安装到一个目录已经是模块搜索路径,或让你的脚本计算添加到正确的道路sys.path。
sys.path
使用-m命令行开关可以像运行脚本一样运行模块。如果您使用python -m pkg.corePython,则会查找__main__.py文件并将其作为脚本运行。该-m交换机将增加当前工作目录到你的模块搜索路径,所以你可以使用这个命令时,你在正确的工作目录,这样就可以了。或者将软件包安装在模块搜索路径上已经存在的目录中。
-m
python -m pkg.core
__main__.py
让您的脚本将正确的目录添加到模块搜索路径(基于os.path.absolute(__file__)以获取当前文件的路径)。考虑到您的脚本 始终 被命名为__main__,并且导入pkg.core.main将添加另一个独立的模块对象;您将拥有两个单独的命名空间。
os.path.absolute(__file__)
pkg.core.main
我也 强烈 建议不要使用隐式相对导入。您可以通过添加嵌套的软件包或具有相同名称的模块来轻松地屏蔽顶级模块和软件包。如果您尝试在包内使用,将pkg/time.py在standard- librarytime模块之前找到。相反,请使用 显式 相对模块引用的Python 3模型;添加到您的所有文件,然后用于明确指出从何处导入模块。import time``pkg __from __future__ import absolute_import``from . import <name>
pkg/time.py
time
import time``pkg
from __future__ import absolute_import``from . import <name>