2010-02-15 1 views
22
내가 플러그인 모듈은 다음과 같이로드 플러그인 시스템 작업입니다

:동적 클래스 로딩 부모 모듈은 '플러그인'을 (를) 찾을 수 없습니다 동안 처리 절대 수입

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 

및 플러그인 작업 : 플러그인 코드에서 각 import 문에 대한이 같은 경고를 얻을.

누군가가 경고의 의미와 내가 잘못하고있는 것을 설명 할 수 있습니까? 비어있는 플러그인 모듈을 따로 생성하여 가져 와서 파이썬을 행복하게 유지해야합니까?

+1

레코드를 들어' 'plugins'''부모 모듈' plugins 'not found'는 [imp.load_module] (https://docs.python.org/2/library/imp.html#imp.load_module)에 전달 된'name' 값에서옵니다. imp.load_module ("plugins.something")'에있는 "plugins.something"을 참조하십시오. 필자의 경우'name' 값은'.something "과 같았고 따라서''plugins'' 대신에''''가 포함되었습니다. – n611x007

답변

14

, 당신은 쉽게 자사의 플러그인 파일을 열거하고로드 pkgutils를 사용할 수 있습니다 (__init__.py 벌금을 포함).

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 

을 그 재미는 주로 해킹입니다!

여기
15

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. 예외에 대한 응답으로 제정신이 아닌 일을 계획 할 수 없다면, 프로그램은 건전하지 못할 것입니다. 디렉토리에 plugins 실제 패키지를한다면
+0

plugins 디렉토리는 패키지가 아니며 가져 오지 않았 음을 유의하십시오. 나머지 코드는 "egg"로 컴파일되고 "python -m"을 사용하여 직접 실행됩니다. 필자는 sys.path에 플러그인 디렉토리를 추가하지 않습니다. – pehrs

+1

맞아요.하지만'foo'라는 플러그인이 있다면'plugins.foo'라고 말했기 때문에'plugins' 패키지 (존재하지 않음)의 일부라고 생각합니다. 'foo.py'에서'import os' (또는'anythingelse'를 가져왔다면)는'plugins'이 실제로 존재하지 않기 때문에 경고를받습니다. –

+0

(즉, 경고를 무시하거나 명명 체계를 변경하거나 Python이 기대하는 것과 일치하도록 구조를 변경하는 옵션이 있다는 의미입니다.) –

4

문제는 모듈 이름에 점 ('.') 함께 : '.'

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

은 포함되지 않습니다 'plugins'이후에, 또는 파이썬은 그것이 모듈 경로라고 생각할 것입니다.

+0

환상적! 정말 고맙습니다! –

0

Python imp 설명서가 업데이트되었으므로 업데이트되었습니다. 이제는이 문제를 find_module() 메소드에서 구체적으로 다루고 있습니다.

이 함수는 계층 적 모듈 이름 (점을 포함하는 이름)을 처리하지 않습니다. 즉 시부, 서브 모듈 패키지의 MP을 찾기 위해 찾아로드 패키지 P 다음 P.__path__로 설정 경로 인수 find_module()를 사용하는 find_module()load_module()를 사용합니다. P 자체에 점으로 구분 된 이름이 있으면이 방법을 재귀 적으로 적용하십시오.

find_module()에 제공 할 때 P.__path__은 이미 목록입니다. 또한 find_module() 설명서에서 패키지를 찾는 방법에 대해 설명합니다.

모듈 패키지,이 None입니다 파일, 경로 패키지 경로와 튜플 PKG_DIRECTORY입니다 설명의 마지막 항목 인 경우. 영업 이익의 질문에서 그래서

은의 RuntimeError 경고없이 플러그인을 가져올 업데이트 된 파이썬 문서의 지시 다음과 같이하십시오

# 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)