使用相对路径名导入包中子模块
问题
将代码组织成包,想用import语句从另一个包名没有硬编码过的包中导入子模块。
解决方案
使用包的相对导入,使一个模块导入同一个包的另一个模块 举个例子,假设在你的文件系统上有mypackage包,组织如下:
mypackage/
__init__.py
A/
__init__.py
spam.py
grok.py
B/
__init__.py
bar.py
如果模块mypackage.A.spam要导入同目录下的模块grok,它应该包括的import语句如下:
# mypackage/A/spam.py
from . import grok
如果模块mypackage.A.spam要导入不同目录下的模块B.bar,它应该使用的import语句如下:
# mypackage/A/spam.py
from ..B import bar
两个import语句都没包含顶层包名,而是使用了spam.py的相对路径。
讨论
在包内,既可以使用相对路径也可以使用绝对路径来导入。 举个例子:
# mypackage/A/spam.py
from mypackage.A import grok # OK
from . import grok # OK
import grok # Error (not found)
像mypackage.A这样使用绝对路径名的不利之处是这将顶层包名硬编码到你的源码中。如果你想重新组织它,你的代码将更脆,很难工作。 举个例子,如果你改变了包名,你就必须检查所有文件来修正源码。 同样,硬编码的名称会使移动代码变得困难。举个例子,也许有人想安装两个不同版本的软件包,只通过名称区分它们。 如果使用相对导入,那一切都ok,然而使用绝对路径名很可能会出问题。
import语句的 .
和 ..
看起来很滑稽, 但它指定目录名.为当前目录,..B为目录../B。这种语法只适用于import。 举个例子:
from . import grok # OK
import .grok # ERROR
尽管使用相对导入看起来像是浏览文件系统,但是不能到定义包的目录之外。也就是说,使用点的这种模式从不是包的目录中导入将会引发错误。
最后,相对导入只适用于在合适的包中的模块。尤其是在顶层的脚本的简单模块中,它们将不起作用。如果包的部分被作为脚本直接执行,那它们将不起作用 例如:
% python3 mypackage/A/spam.py # Relative imports fail
另一方面,如果你使用Python的-m选项来执行先前的脚本,相对导入将会正确运行。 例如:
% python3 -m mypackage.A.spam # Relative imports work
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
2019-08-25 C语言中内存管理规范