carico Classe dinamica in Python 2.6: RuntimeWarning: modulo Parent 'plugins' non trovato durante la manipolazione di importazione assoluta

StackOverflow https://stackoverflow.com/questions/2267984

Domanda

Sto lavorando su un sistema di plugin in cui moduli plugin sono caricati in questo modo:

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

Il codice funziona, ma per ogni istruzione import nel codice del plugin Ho ricevuto un avviso simile a questo:

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

Non ci sono errori vengono segnalati per il codice del programma principale, e i plugin funzionano.

Qualcuno può spiegare che cosa significa l'avviso e quello che facendo male. Ho bisogno di creare un modulo plug-vuoto separatamente e importarlo per mantenere python felice?

È stato utile?

Soluzione

Se la plugins directory fosse un vero e proprio pacchetto (contenuta __init__.py bene), si potrebbe facilmente utilizzare pkgutils per enumerare le sue file dei plugin e caricarli.

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

Tuttavia, può funzionare senza un pacchetto di plug-in in ogni caso, provate questo:

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

Inoltre è possibile fare un pacchetto che esiste solo in fase di esecuzione:

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

sys.modules["plugins"] = plugins
import plugins.testplugin

Comunque hack che era per lo più per divertimento!

Altri suggerimenti

Se la directory dei plugin non ha un __init__.py, non è un pacchetto, in modo che quando si crea plugins.whatever, Python si avverte che una cosa del genere non dovrebbe esistere veramente. (Non poteva essere creata da "import plugins.whatever" non importa quale sia il vostro percorso è.)

Inoltre,

  • Non dividere il /, che è portabile. Utilizzare os.path.split.
  • Non utilizzare .split(".py") per ottenere il nome senza l'estensione, che è bacato. Utilizzare os.path.splitext.
  • Non utilizzare getattr con una stringa letterale. getattr(plugin, "__init__") si scrive plugin.__init__.
  • Sono confuso perché si sta chiamando una funzione __init__ a livello di modulo. Questo non mi sembra giusto. Forse si vuole una funzione "set_logger", o meglio, per creare un'istanza di una classe che prende un registratore.
  • Non utilizzare L = L + some_other_list per estendere un elenco, utilizzare il metodo extend, che ha prestazioni migliori ed è più idiomatica.
  • Non schiacciare eccezioni sconosciute di except Exception. Se non è possibile pianificare di fare qualcosa di sano in risposta ad un'eccezione, il programma non può andare avanti in modo sano.

Il problema qui è con il punto ( '') nel nome del modulo:

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

Non includere un '' dopo 'plugins', o Python penserà che sia un percorso del modulo.

Si può provare ad aggiungere al di sotto dichiarazione all'inizio di istruzioni di importazione.

from __future__ import absolute_import

La documentazione Python imp è stato aggiornato dal momento che questo è stato risposto. E 'ora risolve questo problema in particolare nel metodo find_module() .

  

Questa funzione non gestisce i nomi di modulo gerarchici (nomi contenenti punti). Al fine di trovare PM , cioè, modulo M del pacchetto di P , utilizzare find_module() e load_module() trovare e pacchetto di carico P , e quindi utilizzare find_module() con il path argomento impostato P.__path__. Quando P per sé ha un nome puntato, applicare questa ricetta in modo ricorsivo.

Si noti che P.__path__ è già una lista quando forniscono a find_module() . Si noti inoltre che cosa dice la documentazione find_module() di trovare pacchetti.

  

Se il modulo è un pacchetto, file è None, percorso è il percorso del pacchetto e l'ultimo elemento del Descrizione tupla è < a href = "https://docs.python.org/2/library/imp.html#imp.PKG_DIRECTORY" rel = "nofollow"> PKG_DIRECTORY .

Quindi, dal domanda del PO, per importare il plugin senza gli avvertimenti RuntimeError, seguire le istruzioni fornite nella documentazione Python aggiornamento:

# 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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top