Haciendo un paquete virtual disponible a través de sys.modules

Digamos que tengo un paquete “mylibrary”.

Quiero hacer que “mylibrary.config” esté disponible para la importación, ya sea como un módulo creado dinámicamente o como un módulo importado desde un lugar completamente diferente que básicamente se “montaría” dentro del espacio de nombres “mylibrary”.

Es decir, yo hago:

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

Dada esa configuración:

 >>> import mylibrary.config # -> works >>> from mylibrary import config : cannot import name config 

Aun mas extraño

 >>> import mylibrary.config as X : cannot import name config 

Así que parece que al usar los trabajos de importación directa, las otras formas no. ¿Es posible hacer que esos trabajos también?

Debe aplicar un parche mono al módulo no solo en sys.modules, sino también en su módulo principal:

 >>> 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  

Así como lo siguiente:

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

También necesitas hacer:

 import mylibrary mylibrary.config = config 

Puedes probar algo como esto:

 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