重构 python 模块配置以避免相对导入

Posted

技术标签:

【中文标题】重构 python 模块配置以避免相对导入【英文标题】:Refactoring python module configuration to avoid relative imports 【发布时间】:2010-09-25 15:15:12 【问题描述】:

这与我的previous question 有关。

我了解如何存储和读取配置文件。有ConfigParser和ConfigObj等选择。

考虑这个结构作为假设的“eggs”模块:

蛋/ 常见的/ __init__.py 配置文件 富/ __init__.py 一个.py

'eggs.foo.a' 需要一些配置信息。我目前正在做的是,在'a'中,

导入 egg.common.config
。这样做的一个问题是,如果将“a”移动到模块树中的更深层次,则相对导入会中断。绝对导入不会,但它们要求您的模块位于 PYTHONPATH 上。

上述绝对导入的一个可能替代方案是相对导入。因此,在'a'中,

导入 .common.config

在不讨论相对导入与绝对导入的优点的情况下,我想知道其他可能的解决方案吗?

edit- 删除了 VCS 上下文

【问题讨论】:

相关问题:***.com/questions/171785/… 【参考方案1】:

"imports ... 要求你的模块在你的 PYTHONPATH 上"

没错。

那么,设置PYTHONPATH 有什么问题?

【讨论】:

如果您同时有多个文件在开发中(例如多个分支),如果您每次都需要更改 PYTHONPATH,则很难从一个文件切换到另一个;另外,它添加了一个依赖项,需要一些工作才能受到版本控制。【参考方案2】:

要求来自pkg_resources 的声明也许是你需要的。

【讨论】:

【参考方案3】:

据我从这个问题和以前的问题中了解到,您只需要一条路径即可进入sys.path。如果我们将 git 作为 VCS(在上一个问题中提到)在任何时候只检出一个分支(单个工作目录)。您可以随意切换、合并分支。

【讨论】:

我已经删除了 VCS 上下文,因为我意识到它与我的问题并不真正相关。切换 VCS 最终将这个特殊的设计问题暴露给我。【参考方案4】:

我正在考虑一种更“基于推送”的解决方案。不要导入共享对象(无论是用于配置还是某种实用功能),让*** init 导出它,然后每个中间 init 导入它上面的图层,然后立即重新导出它。

我不确定我的 python 术语是否正确,如果我错了,请纠正我。

像这样,任何需要使用共享对象(在本示例的上下文中表示配置信息)的模块只需从 init 在其自身级别导入它。

这听起来合理/可行吗?

【讨论】:

【参考方案5】:

您可以通过将每个子目录添加到egg/__init__.py 来欺骗导入机制:

__path__.append(__path__[0]+"\\common")
__path__.append(__path__[0]+"\\foo")

然后,您只需从 egg 命名空间导入所有模块;例如import egg.bar(前提是你有文件 egg/foo/bar.py)。 请注意, foo 和 common 不应该是一个包 - 换句话说,它们不应该包含 __init__.py 文件。

这个方案彻底解决了最终移动文件的问题;但是它会使命名空间变平,因此它可能不是那么好,尤其是在大型项目中 - 就个人而言,我更喜欢全名解析。

【讨论】:

以上是关于重构 python 模块配置以避免相对导入的主要内容,如果未能解决你的问题,请参考以下文章

将别名 @ 导入重构为相对路径

在Python中以绝对路径或者相对路径导入文件(或模块)的方法

在 Python 中映射模块导入以便于重构

Python 包内的导入问题(绝对导入和相对导入)

Python3 中 的 绝对导入 与 相对导入

详解Python中的相对导入和绝对导入