Python 2.6의 동적 클래스 로딩 2.6 : Runtimewarning : 부모 모듈 '플러그인'을 찾을 수 없음 절대 가져 오기
-
20-09-2019 - |
문제
플러그인 모듈이 다음과 같이로드되는 플러그인 시스템에서 작업 중입니다.
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)