2011-02-05 4 views
3

파이썬 소스 파일에 대해 지정된 경로를 구문 분석하고 가져온 각 모듈에 각 파일 및 DoStuff ™을 가져 오려고합니다. 어떻게 주어진 모듈은 패키지의 일부임을 imp.load_module 알 수 있습니까경로에 각 .py 파일로드 - imp.load_module은 상대적 가져 오기에 대해 불평합니다

def ParsePath(path): 
    for root, dirs, files in os.walk(path): 
     for source in (s for s in files if s.endswith(".py")): 
      name = os.path.splitext(os.path.basename(source))[0] 
      m = imp.load_module(name, *imp.find_module(name, [root])) 
      DoStuff(m) 

위의 코드는 작동하지만, 패키지는

내 질문은 기본적으로 ValueError: Attempted relative import in non-package를 인식되지 않습니다?

+0

어떤 종류의 디렉토리 구조가 있습니까? 함수에 전달한'path'가 패키지의 루트 경로입니까? – shang

+0

이 질문의 목적 중 일부는 경로에 관계없이 패키지를 수동으로 만드는 방법을 이해하는 것입니다. 물론, ParsePath를 둘러 볼 수있어 항상 내용 앞에 '__init __. py'가 포함 된 디렉토리를 가져 오려고합니다. 그게 효과가있을 것이라고 추측하지만 IMHO 문제를 해결하는 올바른 방법은 아닙니다. – porgarmingduod

답변

3

직접 가져 오기 프로토콜 방식 주어진 모듈은 패키지의 일부임을 load_module 말할 수 없습니다. PEP 302 New Import Hooks

에서 촬영 내장 __import__ 기능 (import.c에 PyImport_ImportModuleEx 라고도 함) 다음 가져 오기를 수행 모듈 패키지 또는 패키지의 서브 모듈인지 여부를 확인합니다. 실제로 (a의 하위 모듈) 패키지 인 경우 패키지 (하위 모듈의 상위 패키지)에 대해 상대적인 가져 오기를 먼저 시도합니다. 예를 들어 패키지 이름이 "spam"인 경우 "eggs 가져 오기"를 수행하면 먼저 "spam.eggs"모듈을 찾습니다. 실패한 경우 가져 오기는 절대 가져 오기로 계속 진행되며 "eggs"모듈을 찾습니다. 점을 찍은 이름 가져 오기는 거의 똑같이 작동합니다. 패키지 "스팸"이 "가져 오기 eggs.bacon"(및 "spam.eggs"가 있고 그 자체가 패키지 인 경우) 인 경우 "spam.eggs.bacon"이 시도됩니다. 그게 실패하면 "eggs.bacon"은 입니다. (이들은 수입 프로토콜의 구현을위한 관련이없는 가 여기에 설명되지 않은 더 미묘한 차이가 있지만.)

메커니즘에서 아래로 깊은는 점으로 구분 된 이름 가져 오기는 그 구성 요소에 의해 분리된다. "import spam.ham"의 경우 먼저 "가져 오기 스팸"은 이고 성공한 경우에만 "ham"이 하위 모듈로 가져 오기 "spam"입니다.

가져 오기 프로그램 프로토콜은 개 개별 개 수준에서 작동합니다. 가져 오기 도구가 "spam.ham"에 대한 요청을 받으면 "spam"모듈을 이미 가져 왔습니다.

그런 다음 하위 모듈을로드하기 전에 기본 가져 오기에서 수행하는 작업을 시뮬레이트하고 상위 패키지를로드해야합니다.

+0

필자는 모듈, 패키지 및 가져 오기 작업이 파이썬에서 유일하게 불만족 스럽다고 생각합니다. 며칠 전에 이미 해킹 된 솔루션을 만들었지 만, 당신이 일을 정리할 수 있었다는 것에 감사드립니다. "할 수 없다"는 만족스럽지 않으면 적어도 유용 할 수 있습니다. – porgarmingduod

2

기능 imp.find_module은 항상 점없이 일반 모듈 이름이 필요하지만 imp.load_module의 문서는이 패키지의 서브 모듈의 경우

이름 인수, 패키지 이름을 포함한 전체 모듈 이름 (표시 말한다).

그래서 당신이 시도 할 수 :

def ParsePath(path): 
    for root, dirs, files in os.walk(path): 
     for source in (s for s in files if s.endswith(".py")): 
      name = os.path.splitext(os.path.basename(source))[0] 
      full_name = os.path.splitext(source)[0].replace(os.path.sep, '.') 
      m = imp.load_module(full_name, *imp.find_module(name, [root])) 
      DoStuff(m) 
+0

글쎄, 일종의 올바른 아이디어가있다. (게시 한 코드의 일부 오류를 제외하고는 절대 작동하지 않는다는 사실과 함께) 실제로 도움이되지는 않는다. 당신의 첫 번째 코멘트에 대해 설명하면서, 나는 원숭이 패치를 찾고 있지 않습니다. 나는 내 원숭이 패치를 만들 수있다. ** 답변 **을 찾고 있는데, 이것이 아닙니다. – porgarmingduod

+0

글쎄, 나는 당신의 질문을 정확하게 이해하지 못한다. 'imp.load_module'이 모듈이 패키지의 일부라는 것을 알 수있는 방법을 찾고 있다고 말했고 패키지 이름을 포함하는 정규화 된 (즉, 점으로 구분 된) 이름을 제공하는 방법이 있습니다. – shang

0

나는 동일한 문제가있었습니다.좋은 소식은 그것을 할 수있는 방법이 있지만, impimportlib의 조합을 사용해야한다는 것입니다. 이 sub_module 우리가 이미 부모 패키지를로드 한 및 서브 모듈이 그것으로 상대를 가져오고 있는지 알고 importlib 올바르게 장착되어 있기 때문에 상대 모듈 경로를 사용하여 가져올 수

import imp 
import importlib 
package_path = r"C:\path_to_package" 

package_name = "module" 
module_absolute_name = "module.sub_module" 
module_relative_name = ".sub_module" 

# Load the package first 
package_info = imp.find_module(package_name, [package_path]) 
package_module = imp.load_module(package_name, *package_info) 

# Try an absolute import 
importlib.import_module(module_absolute_name, package_name) 

# Try a relative import 
importlib.import_module(module_relative_name, package_name) 

: 여기에 예시입니다 .

저는이 솔루션이 파이썬 2. *에 고정되어있는 사람들에게만 필요하다고 생각합니다.하지만이를 확인하는 사람이 필요합니다.

관련 문제