Python 2.6中的动态类加载:RuntimeWarning:处理绝对导入时找不到父模块"插件"

peh*_*hrs 23 python import plugins dynamic-class-loaders

我正在开发一个插件系统,插件模块加载如下:

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
Run Code Online (Sandbox Code Playgroud)

代码有效,但是对于插件代码中的每个import语句,我都会收到如下警告:

plugins/plugin.py:2: RuntimeWarning: Parent module 'plugins' not found while handling absolute import
  import os
Run Code Online (Sandbox Code Playgroud)

没有报告主程序代码的错误,插件工作.

有人可以解释警告意味着什么,我做错了什么.我是否需要单独创建一个空的插件模块并导入它以保持python的快乐?

Mik*_*ham 16

如果plugins目录没有__init__.py,那么它不是一个包,所以当你创建时plugins.whatever,Python警告你这样的东西不应该存在.(import plugins.whatever无论你的路径是什么,它都无法通过" " 创建.)

也,

  • 不要拆分/,这是不可移植的.使用os.path.split.
  • 不要使用.split(".py")没有扩展名来获取名称,这是错误的.使用os.path.splitext.
  • 不要使用getattr字符串文字.getattr(plugin, "__init__")是拼写的plugin.__init__.
  • 我很困惑你为什么要调用模块级__init__函数.这似乎不对.也许您想要一个"set_logger"函数或更好的函数来实例化一个带记录器的类.
  • 不要L = L + some_other_list用于扩展列表,使用extend具有更好性能且更惯用的方法.
  • 不要压缩未知的例外except Exception.如果你不能计划做一些理智的事情来回应异常,那么你的程序就不能理智.


u0b*_*6ae 14

如果目录plugins是真正的包(包含__init__.py正常),您可以轻松地使用pkgutils枚举其插件文件并加载它们.

import pkgutil
# import our package
import plugins
list(pkgutil.iter_modules(plugins.__path__))
Run Code Online (Sandbox Code Playgroud)

但是,无论如何它都可以在没有插件包的情况下工作,试试这个:

import pkgutil
list(pkgutil.iter_modules(["plugins"]))
Run Code Online (Sandbox Code Playgroud)

还可以创建仅在运行时存在的包:

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

sys.modules["plugins"] = plugins
import plugins.testplugin
Run Code Online (Sandbox Code Playgroud)

然而,那个黑客主要是为了好玩!


Fer*_*der 6

这里的问题是模块名称中的点('。'):

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

不要包含“。” 在“插件”之后,否则Python会认为这是模块路径。