从包的__init__.py中屏蔽python子模块 [英] Mask a python submodule from its package's __init__.py

查看:242
本文介绍了从包的__init__.py中屏蔽python子模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

特定的设置要求我在 __ init __。py 中创建局部变量,这些变量将掩盖模块来自同一个包裹。

A specific setup requires me to create local variables in __init__.py that shall mask modules from the same package.

例如变量 y (在 __ init __。py 的本地上下文中)将隐藏模块 y的.py 。语句 import xy 将产生局部变量而不是加载模块。

E.g. the variable y (in the local context of __init__.py) shall hide the module y.py. The statement import x.y shall yield the local variable instead of loading the module.

如果你不这样做想了解具体的设置,向下滚动到问题;没有细节,这是可以理解的。

我已经实现了一组Python 2.7个软件包,每个软件包可能需要单独的配置设置。为方便起见,我计划提供配置默认值每个包,任何使用其中一个包的人都可以在本地覆盖。

I have implemented a set of Python 2.7 packages, each of which may require individual configuration settings. For convenience, I was planning to provide configuration defaults per package that can be locally overwritten by whoever uses one of the packages.

(其基本原理是在将应用程序部署到运行特定环境(服务器,工作站,笔记本电脑等)的计算机时分发默认设置,但同时允许覆盖配置而不会弄乱本地存储库或重置本地适应代码更新。)

目录结构示例为:

~/pkg/
  |
  +- package_a/
  |    |
  |    +- __init__.py
  |    +- mod_x.py
  |    +- mod_y.py
  |
  +- package_b/
  |    |
  |    +- __init__.py
  |    +- mod_z.py
  |
  +- config/
  |    |
  |    +- __init__.py
  |    +- package_a.py # Should locally override <pkg>_sample.py
  |    +- package_a_sample.py
  |    +- package_b_sample.py
  |
  +- test_this.py

我想访问存储在<$下的设置c $ c> config / 喜欢常规模块导入,例如:

I'd like to access the settings stored under config/ like regular module imports, e.g.:

# ~/pkg/test_this.py
import config.package_a as cfg_a

..但是让它隐式切换到覆盖文件(如果存在)。

... but have it implicitly switch to the overriding file, if it exists.

按顺序以某种方式自动化进程,我动态创建指向正确配置文件导入的局部变量。使用 imp 包,我可以导入一个模块,并特别指定它。 (即在运行时,您无法区分< pkg> _sample.py < pkg> .py 已加载以提供配置。)

In order to somehow automate the process, I am dynamically creating local variables pointing to the correct configuration file imports. Using the imp package, I can import a module and specifically naming it at the same time. (I.e. at runtime, you cannot distinguish whether <pkg>_sample.py or <pkg>.py was loaded to serve the configuration.)

我终于得到了这个:

# ~/pkg/config/__init__.py
import os
import imp

__all__ = ['datastore']
_cfgbase = os.path.dirname(os.path.realpath(__file__))

for cfgmodule in __all__:
    if os.path.isfile(os.path.join(_cfgbase, cfgmodule + '.py')):
        locals()[cfgmodule] = imp.load_source(
            cfgmodule, os.path.join(_cfgbase, cfgmodule + '.py'))
    else:
        locals()[cfgmodule] = imp.load_source(
            cfgmodule, os.path.join(_cfgbase, cfgmodule + '_sample.py'))

这实际上创建了对所需源文件的本地引用(省略< pkg> _sample .py < pkg> .py 存在于 config /

This actually creates a local reference to the required source files (omitting <pkg>_sample.py when <pkg>.py is existing in config/.

如果使用从配置导入package_a as cfg_a 。

基本上,这个问题可能会回落到众所周知的从x import y -thing导入xy vs。

Essentially, this question may fall back to the well-known import x.y vs from x import y-thing.

这里有区别。

我知道 import xy 需要 y 作为模块。是否任何可能性隐藏模块在其包的 __ init __。py 中并在导入时提供本地变量instad

I know that import x.y requires y to be a module. Is there any possibility to hide a module in its package's __init__.py and to provide a local variable instad on import?


  • 来自x import y 产生局部变量 y 来自 x __ init __。py

  • import xy 始终导入模块,即使本地变量 y 存在于 __ init __。py

  • from x import y yields the local variable y from x's __init__.py
  • import x.y always imports the module, even if a local variable y exists in __init__.py.

我无法强迫所有人始终使用以前的导入声明,人们喜欢在他们的代码中使用后者。

I cannot force everyone to always use the former import statement, people like to use the latter one in their code.

这里有任何建议吗?

编辑:修正了标题。抱歉。

感谢@ martijn-pieters指出 sys.modules

Thanks @martijn-pieters for pointing out sys.modules.

实际上,我的方法可以完美地工作,而无需将新导入显式添加到 sys .modules ,因为我在正确命名新导入时失败了:

Actually, my approach would have worked perfectly without explicitly adding the new import to sys.modules, as I just failed at properly naming the new imports:

locals()[cfgmodule] j= imp.load_source(
    'config.' + cfgmodule, os.path.join(_cfgbase, cfgmodule + '.py'))

这解决了这个问题,因为它没有用 canonical 名称注册新的子模块(这里: package_a )但将其注册为我的 config 包的子模块。

This solves the issue, as it does not register the new submodule with its canonical name (here: package_a) but registers it as a submodule of my config package.

非常感谢!

推荐答案

import xy 并不需要 y 成为一个模块。 import xy 查找'x''x.y' sys.modules 结构中的键。如果两者都找到,则 x 绑定到 sys.modules ['x'] 。只有当'x.y'不存在时,Python才会寻找要加载的模块。

import x.y does not really require y to be a module. import x.y looks up the 'x' and 'x.y' keys in the sys.modules structure. If both are found, then x is bound to sys.modules['x']. Only if 'x.y' does not exist, is Python going to look for a module to load.

然后,诀窍是将 y 填入 sys.modules

sys.modules['x.y'] = y

这篇关于从包的__init__.py中屏蔽python子模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆