2008-12-15 60 views
9

假设我有一个包“mylibrary”。通过sys.modules制作虚拟包

我想让“mylibrary.config”可用于导入,既可以作为动态创建的模块,也可以从完全不同的地方导入,然后基本上将“挂载”到“mylibrary”命名空间中。

也就是说,我做的:

import sys, types 
sys.modules['mylibrary.config'] = types.ModuleType('config') 

鉴于设置:

>>> import mylibrary.config # -> works 

>>> from mylibrary import config 
<type 'exceptions.ImportError'>: cannot import name config 

更奇怪的是:

>>> import mylibrary.config as X 
<type 'exceptions.ImportError'>: cannot import name config 

如此看来,使用直接进口的作品,其他形式不要。是否有可能使这些工作以及?

回答

13

你需要猴子补丁模块只进不出sys.modules中,还融入其父模块:

>>> import sys,types,xml 
>>> xml.config = sys.modules['xml.config'] = types.ModuleType('xml.config') 
>>> import xml.config 
>>> from xml import config 
>>> from xml import config as x 
>>> x 
<module 'xml.config' (built-in)> 
1

你可以尝试这样的事情:

class VirtualModule(object): 
    def __init__(self, modname, subModules): 
    try: 
     import sys 
     self._mod = __import__(modname) 
     sys.modules[modname] = self 
     __import__(modname) 
     self._modname = modname 
     self._subModules = subModules 
    except ImportError, err: 
     pass # please signal error in some useful way :-) 
    def __repr__(self): 
    return "Virtual module for " + self._modname 
    def __getattr__(self, attrname): 
    if attrname in self._subModules.keys(): 
     import sys 
     __import__(self._subModules[attrname]) 
     return sys.modules[self._subModules[attrname]] 
    else: 
     return self._mod.__dict__[attrname] 


VirtualModule('mylibrary', {'config': 'actual_module_for_config'}) 

import mylibrary 
mylibrary.config 
mylibrary.some_function 
1

除了以下:

import sys, types 
config = types.ModuleType('config') 
sys.modules['mylibrary.config'] = config 

你也需要做:

import mylibrary 
mylibrary.config = config