通过sys.modules提供虚拟包

时间:2008-12-15 11:20:15

标签: python import module

说我有一个包“mylibrary”。

我想让“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

所以似乎使用直接导入工作,其他形式则不然。是否有可能使这些工作?

3 个答案:

答案 0 :(得分:14)

您需要将模块不仅修补到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 :(得分:2)

以及以下内容:

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

您还需要:

import mylibrary
mylibrary.config = config

答案 2 :(得分: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