una resueltos programacion polimorfismo otra orientada objetos metodo llamar instanciar herencia ejercicios ejemplo como clases clase python plugins import dynamic-class-loaders

resueltos - programacion orientada a objetos python pdf



Carga dinámica de clases en Python 2.6: RuntimeWarning: no se encuentran los ''complementos'' del módulo principal mientras se maneja la importación absoluta (4)

Estoy trabajando en un sistema de complemento donde los módulos de complementos se cargan así:

def load_plugins(): plugins=glob.glob("plugins/*.py") instances=[] for p in plugins: try: name=p.split("/")[-1] name=name.split(".py")[0] log.debug("Possible plugin: %s", name) f, file, desc=imp.find_module(name, ["plugins"]) plugin=imp.load_module(''plugins.''+name, f, file, desc) getattr(plugin, "__init__")(log) instances=instances+plugin.get_instances() except Exception as e: log.info("Failed to load plugin: "+str(p)) log.info("Error: %s " % (e)) log.info(traceback.format_exc(e)) return instances

El código funciona, pero para cada instrucción de importación en el código del complemento recibo una advertencia como esta:

plugins/plugin.py:2: RuntimeWarning: Parent module ''plugins'' not found while handling absolute import import os

No se informan errores para el código del programa principal, y los complementos funcionan.

¿Alguien puede explicar lo que significa la advertencia y lo que estoy haciendo mal? ¿Debo crear un módulo de complementos vacío por separado e importarlo para mantener a python satisfecho?


El problema aquí es con el punto (''.'') En el nombre del módulo:

imp.load_module(''plugins.''+name, f, file, desc)

No incluya un ''.'' después de ''complementos'', o Python pensará que es una ruta de módulo.


La documentación Python imp se ha actualizado desde que se respondió. Ahora aborda este problema específicamente en el método find_module() .

Esta función no maneja nombres de módulos jerárquicos (nombres que contienen puntos). Para encontrar PM , es decir, el submódulo M del paquete P , use find_module() y imp.load_module para buscar y cargar el paquete P , y luego use find_module() con el argumento de ruta establecido en P.__path__ . Cuando P mismo tiene un nombre punteado, aplique esta receta recursivamente.

Tenga en cuenta que P.__path__ ya es una lista al suministrarlo a find_module() . También tenga en cuenta lo que dice la documentación de find_module() sobre la búsqueda de paquetes.

Si el módulo es un paquete, el archivo es None , pathname es la ruta del paquete y el último elemento en la descripción tuple es PKG_DIRECTORY .

Entonces, de la pregunta del OP, para importar el complemento sin las advertencias de RuntimeError , siga las instrucciones en la documentación actualizada de Python:

# first find and load the package assuming it is in # the current working directory, ''.'' f, file, desc = imp.find_module(''plugins'', [''.'']) pkg = imp.load_module(''plugins'', f, file, desc) # then find the named plugin module using pkg.__path__ # and load the module using the dotted name f, file, desc = imp.find_module(name, pkg.__path__) plugin = imp.load_module(''plugins.'' + name, f, file, desc)


Si el directorio de complementos no tiene un __init__.py , no es un paquete, así que cuando creas plugins.whatever , Python te advierte que tal cosa no debería existir realmente. (No podría ser creado por " import plugins.whatever " sin importar cuál sea tu ruta).

También,

  • No se divida en / , lo que no es portátil. Use os.path.split .
  • No use .split(".py") para obtener el nombre sin la extensión, que tiene errores. Use os.path.splitext .
  • No use getattr con un literal de cadena. getattr(plugin, "__init__") se escribe plugin.__init__ .
  • Estoy confundido por qué está llamando a una función __init__ nivel de __init__ . Esto no parece correcto. Quizás desee una función "set_logger" o mejor, para instanciar una clase que tenga un registrador.
  • No use L = L + some_other_list para extender una lista, use el método extend , que tiene un mejor rendimiento y es más idiomático.
  • No squash excepciones desconocidas por excepción except Exception . Si no puede planear hacer algo sensato en respuesta a una excepción, su programa no puede seguir sano.

Si los plugins del directorio eran un paquete real (contenía __init__.py fine), podría usar pkgutils fácilmente para enumerar sus archivos de complementos y cargarlos.

import pkgutil # import our package import plugins list(pkgutil.iter_modules(plugins.__path__))

Sin embargo, puede funcionar sin un paquete de complemento de todos modos, intente esto:

import pkgutil list(pkgutil.iter_modules(["plugins"]))

También es posible crear un paquete que solo existe en tiempo de ejecución:

import types import sys plugins = types.ModuleType("plugins") plugins.__path__ = ["plugins"] sys.modules["plugins"] = plugins import plugins.testplugin

Sin embargo, ese truco fue principalmente por diversión.