Python 2.6의 동적 클래스 로딩 2.6 : Runtimewarning : 부모 모듈 '플러그인'을 찾을 수 없음 절대 가져 오기

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

문제

플러그인 모듈이 다음과 같이로드되는 플러그인 시스템에서 작업 중입니다.

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

코드는 작동하지만 플러그인 코드의 각 가져 오기 명령문에 대해 다음과 같은 경고를 얻습니다.

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

기본 프로그램 코드에는 오류 가보고되지 않으며 플러그인이 작동합니다.

누군가 경고의 의미와 내가 무엇을 잘못하고 있는지 설명 할 수 있습니까? 빈 플러그인 모듈을 별도로 만들고 Python을 행복하게 유지하기 위해 가져와야합니까?

도움이 되었습니까?

해결책

디렉토리 인 경우 plugins 실제 패키지였습니다 (포함 __init__.py Fine), Pkgutils를 쉽게 사용하여 플러그인 파일을 열거하고로드 할 수 있습니다.

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

그러나 어쨌든 플러그인 패키지없이 작동 할 수 있습니다.

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

또한 런타임에만 존재하는 패키지를 만들 수 있습니다.

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

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

그러나 주로 재미를위한 해킹!

다른 팁

플러그인 디렉토리에 An이없는 경우 __init__.py, 그것은 패키지가 아니므로 만들 때 plugins.whatever, 파이썬은 그런 것이 실제로 존재해서는 안된다고 경고합니다. (그것은 "만들 수 없었다"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. 예외에 대한 응답으로 제정신 일을 계획 할 수 없다면 프로그램은 Sanely가 진행될 수 없습니다.

여기서 문제는 모듈 이름의 점 ( '.')에 관한 것입니다.

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

''를 포함하지 마십시오. '플러그인'또는 파이썬은 모듈 경로라고 생각합니다.

가져 오기가 시작될 때 아래 명령문을 추가 할 수 있습니다.

from __future__ import absolute_import

파이썬 imp 이에 대한 답변 이후 문서가 업데이트되었습니다. 이제이 문제를 구체적으로 다루고 있습니다 find_module() 방법.

이 기능은 계층 적 모듈 이름 (도트를 포함하는 이름)을 처리하지 않습니다. 찾기 위해 오후, 즉, 하위 모듈입니다 패키지의 , 사용 find_module() 그리고 load_module() 패키지를 찾고로드합니다 , 그런 다음 사용합니다 find_module() 이랑 인수가 설정되었습니다 P.__path__. 언제 그 자체는 점선 이름이 있습니다.이 레시피를 재귀 적으로 적용하십시오.

주목하십시오 P.__path__ 공급할 때 이미 목록입니다 find_module(). 또한 무엇을 주목하십시오 find_module() 문서는 패키지 찾기에 대해 언급합니다.

모듈이 패키지 인 경우 파일 ~이다 None, PathName 패키지 경로와 마지막 항목은 설명 튜플은 PKG_DIRECTORY.

OP의 질문에서 RuntimeError 경고, 업데이트 된 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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top