从包中屏蔽python子模块';s_uuuinit_uuuuu.py 短版

从包中屏蔽python子模块';s_uuuinit_uuuuu.py 短版,python,python-2.7,import,module,Python,Python 2.7,Import,Module,一个特定的设置要求我在\uuuu init\uuuuu.py中创建本地变量,该变量将屏蔽同一软件包中的模块 例如,变量y(在的本地上下文中)应隐藏模块y.py。语句import x.y应产生局部变量,而不是加载模块 如果您不想阅读有关特定设置的内容,请向下滚动至问题;没有细节是可以理解的 详细说明 我已经实现了一组Python 2.7包,每个包都可能需要单独的配置设置。为了方便起见,我计划为每个包提供配置默认值,使用其中一个包的任何人都可以在本地覆盖这些默认值 (这样做的基本原理是在将应用程序部

一个特定的设置要求我在
\uuuu init\uuuuu.py
中创建本地变量,该变量将屏蔽同一软件包中的模块

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

如果您不想阅读有关特定设置的内容,请向下滚动至问题;没有细节是可以理解的

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

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

目录结构示例为:

~/pkg/
|
+-a包/
|    |
|+-\\\\\\\\\.py
|+-mod_x.py
|+-mod_y.py
|
+-b包/
|    |
|+-\\\\\\\\\.py
|+-mod_z.py
|
+-配置/
|    |
|+-\\\\\\\\\.py
|+-package_a.py#应本地覆盖_sample.py
|+-package_a_sample.py
|+-package_b_sample.py
|
+-测试这个.py
我想访问存储在
config/
下的设置,就像常规模块导入一样,例如:

#~/pkg/test\u this.py
将config.package_a导入为cfg_a
。。。但是,如果存在重写文件,则隐式地将其切换到重写文件

我的解决方法 为了以某种方式自动化该过程,我正在动态创建指向正确配置文件导入的局部变量。使用
imp
包,我可以导入一个模块,同时对其进行专门命名。(即,在运行时,您无法区分是加载了
\u sample.py
还是
.py
来提供配置。)

我最终得出以下结论:

#~/pkg/config/uuu init.py
导入操作系统
进口小商品
__所有数据存储
_cfgbase=os.path.dirname(os.path.realpath(_文件__))
对于所有中的CFG模块:
如果os.path.isfile(os.path.join(_cfgbase,cfgmodule+'.py')):
locals()[cfgmodule]=imp.load\u源(
cfgmodule,os.path.join(_cfgbase,cfgmodule+'.py'))
其他:
locals()[cfgmodule]=imp.load\u源(
cfgmodule,os.path.join(_cfgbase,cfgmodule+''u sample.py'))
这实际上创建了对所需源文件的本地引用(当
config/
中存在
.py
时,省略
\u sample.py

如果将配置导入包a中的
用作cfg\u a
,我可以从其他模块/脚本中使用它

问题 从本质上讲,这个问题可以追溯到众所周知的
import x.y与from x import y
-事情

但是这里有一个区别

我知道,
import x.y
需要
y
作为一个模块。是否有任何可能性将模块隐藏在其包的
\uu init\uuuuuy.py
中,并在导入时提供局部变量instad

  • from x import y
    生成本地变量
    y
    from
    x
    \uuu init\uuuuuuuuuuuy
  • import x.y
    始终导入模块,即使
    \uuuu init\uuuu.py
    中存在局部变量
    y
我不能强迫每个人总是使用前一个import语句,人们喜欢在代码中使用后一个

有什么建议吗

编辑:固定标题。对不起

解决方案 感谢@martijn pieters指出
sys.modules

实际上,如果不显式地将新导入添加到
sys.modules
,我的方法将非常有效,因为我无法正确命名新导入:

locals()[cfgmodule] j= imp.load_source(
    'config.' + cfgmodule, os.path.join(_cfgbase, cfgmodule + '.py'))
这就解决了这个问题,因为它不使用其规范名称(此处:
package_a
)注册新的子模块,而是将其注册为my
config
包的子模块


非常感谢!

import x.y
实际上并不要求
y
成为模块。
import x.y
sys.modules
结构中查找
'x'
'x.y'
键。如果找到了这两个键,那么
x
将绑定到
sys.modules['x']
。只有当
'x.y'
不存在时,Python才会寻找要加载的模块

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

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

如果您能解释为什么需要/想要这样做,这将对我们有所帮助?@TomDalton可能我对此不够清楚。我希望所有代码和行为都完全相同,无论用户是否为个别更改创建了本地配置副本。感谢您指出这一点。但是,我在使用此解决方案时遇到了其他问题。这会掩盖问题从我的
站点包安装的包
,如果名称部分冲突:
导入config.芹菜作为cfg\u ce;print(芹菜)
产生:
我认为这是由于我的
imp.load\u源(…)
语句及其在
\u init\uuuuuuuuuuuuuuuuuuuuuuuuuuuy.py