从包中屏蔽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
fromx
的\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
)注册新的子模块,而是将其注册为myconfig
包的子模块
非常感谢!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