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

时间:2021-03-15 13:13:16

This is related to a previous question of mine.

这与我之前的一个问题有关。

I understand how to store and read configuration files. There are choices such as ConfigParser and ConfigObj.

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

Consider this structure for a hypothetical 'eggs' module:

考虑这个假设的“蛋”模块的结构:

eggs/
  common/
    __init__.py
    config.py
  foo/
    __init__.py
    a.py

'eggs.foo.a' needs some configuration information. What I am currently doing is, in 'a',

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

import eggs.common.config
. One problem with this is that if 'a' is moved to a deeper level in the module tree, the relative imports break. Absolute imports don't, but they require your module to be on your PYTHONPATH.

A possible alternative to the above absolute import is a relative import. Thus, in 'a',

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

import .common.config

Without debating the merits of relative vs absolute imports, I was wondering about other possible solutions?

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

edit- Removed the VCS context

edit-删除了VCS上下文

5 个解决方案

#1


2  

"imports ... require your module to be on your PYTHONPATH"

“导入...要求你的模块在你的PYTHONPATH上”

Right.

So, what's wrong with setting PYTHONPATH?

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

#2


0  

require statement from pkg_resources maybe what you need.

来自pkg_resources的require语句可能就是你需要的。

#3


0  

As I understand it from this and previous questions you only need one path to be in sys.path. If we are talking about git as VCS (mentioned in previous question) when only one branch is checked out at any time (single working directory). You can switch, merge branches as frequently as you like.

据我所知,在此问题和之前的问题中,您只需要在sys.path中使用一条路径。如果我们将git称为VCS(在前一个问题中提到),那么任何时候只能检出一个分支(单个工作目录)。您可以根据需要随时切换,合并分支。

#4


0  

I'm thinking of something along the lines of a more 'push-based' kind of solution. Instead of importing the shared objects (be they for configuration, or utility functions of some sort), have the top-level init export it, and each intermediate init import it from the layer above, and immediately re-export it.

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

I'm not sure if I've got the python terminology right, please correct me if I'm wrong.

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

Like this, any module that needs to use the shared object(which in the context of this example represents configuration information) simply imports it from the init at its own level.

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

Does this sound sensible/feasible?

这听起来合理/可行吗?

#5


0  

You can trick the import mechanism, by adding each subdirectory to egg/__init__.py:

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

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

then, you simply import all modules from the egg namespace; e.g. import egg.bar (provided you have file egg/foo/bar.py).
Note that foo and common should not be a package - in other words, they should not contain __init__.py file.

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

This solution completely solves the issue of eventually moving files around; however it flattens the namespace and therefore it may not be as good, especially in big projects - personally, I prefer full name resolution.

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

#1


2  

"imports ... require your module to be on your PYTHONPATH"

“导入...要求你的模块在你的PYTHONPATH上”

Right.

So, what's wrong with setting PYTHONPATH?

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

#2


0  

require statement from pkg_resources maybe what you need.

来自pkg_resources的require语句可能就是你需要的。

#3


0  

As I understand it from this and previous questions you only need one path to be in sys.path. If we are talking about git as VCS (mentioned in previous question) when only one branch is checked out at any time (single working directory). You can switch, merge branches as frequently as you like.

据我所知,在此问题和之前的问题中,您只需要在sys.path中使用一条路径。如果我们将git称为VCS(在前一个问题中提到),那么任何时候只能检出一个分支(单个工作目录)。您可以根据需要随时切换,合并分支。

#4


0  

I'm thinking of something along the lines of a more 'push-based' kind of solution. Instead of importing the shared objects (be they for configuration, or utility functions of some sort), have the top-level init export it, and each intermediate init import it from the layer above, and immediately re-export it.

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

I'm not sure if I've got the python terminology right, please correct me if I'm wrong.

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

Like this, any module that needs to use the shared object(which in the context of this example represents configuration information) simply imports it from the init at its own level.

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

Does this sound sensible/feasible?

这听起来合理/可行吗?

#5


0  

You can trick the import mechanism, by adding each subdirectory to egg/__init__.py:

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

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

then, you simply import all modules from the egg namespace; e.g. import egg.bar (provided you have file egg/foo/bar.py).
Note that foo and common should not be a package - in other words, they should not contain __init__.py file.

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

This solution completely solves the issue of eventually moving files around; however it flattens the namespace and therefore it may not be as good, especially in big projects - personally, I prefer full name resolution.

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