[python] __init__.py를 사용하여“비 패키지에서 시도 된 상대 가져 오기”를 수정하는 방법

다음 디렉토리 구조로 PEP 328 을 따르려고합니다 .

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

에서 core_test.py나는 다음과 같은 import 문을

from ..components.core import GameLoopEvents

그러나 실행할 때 다음 오류가 발생합니다.

tests$ python core_test.py
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

주위를 검색하면 ” __init__.py와도상대 경로가 작동하지 않습니다 “와 ” 상대 경로에서 모듈 가져 오기 “가 발견되었지만 도움이되지 않았습니다.

여기서 누락 된 것이 있습니까?



답변

예. 패키지로 사용하지 않습니다.

python -m pkg.tests.core_test


답변

Ignacio Vazquez-Abrams의 답변 을 자세히 설명하려면 다음과 같이하십시오.

파이썬 가져 오기 메커니즘은 __name__현재 파일과 관련하여 작동 합니다. 파일을 직접 실행할 때는 일반적인 이름이 없지만 "__main__"대신 이름이 있습니다. 따라서 상대 수입품이 작동하지 않습니다.

Igancio가 제안한대로 -m옵션을 사용하여 실행할 수 있습니다. 패키지로 스크립트로 실행되도록 패키지의 일부가있는 경우 해당 __package__속성을 사용하여 해당 파일에 패키지 계층 구조에있는 이름 을 지정할 수도 있습니다 .

자세한 내용은 http://www.python.org/dev/peps/pep-0366/ 을 참조하십시오.


답변

import components.core현재 디렉토리를 sys.path다음에 추가하면 직접 사용할 수 있습니다 .

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))


답변

스크립트를 시작하려는 방법에 따라 다릅니다.

고전적인 방법으로 명령 행 에서 UnitTest시작하려면 다음과 같습니다.

python tests/core_test.py

이 경우 ‘components’‘tests’ 는 형제 폴더이므로 sys.path 모듈 의 insert 또는 append 메소드를 사용하여 상대 모듈을 가져올 수 있습니다 . 다음과 같은 것 :

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

그렇지 않으면 ‘-m’인수를 사용하여 스크립트를 시작할 수 있습니다 (이 경우 패키지에 대해 이야기하고 있으므로 ‘.py’ 확장자 를 지정해서는 안 됨 ).

python -m pkg.tests.core_test

이 경우 상대 임포트를 간단하게 사용할 수 있습니다.

from ..components.core import GameLoopEvents

마지막으로 두 가지 접근 방식을 혼합하여 스크립트 호출 방식에 관계없이 스크립트가 작동하도록 할 수 있습니다. 예를 들면 다음과 같습니다.

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents


답변

core_test.py에서 다음을 수행하십시오.

import sys
sys.path.append('../components')
from core import GameLoopEvents


답변

유스 케이스가 테스트를 실행하기위한 것이고 그것이 솔기 인 경우 다음을 수행 할 수 있습니다. 테스트 스크립트를 실행 python core_test.py하는 대신와 같은 테스트 프레임 워크 를 사용하십시오 pytest. 그런 다음 명령 행에 다음을 입력 할 수 있습니다.

$$ py.test

그러면 디렉토리에서 테스트가 실행됩니다. 이 문제 걸어 다니는 __name__존재 __main__@BrenBarn 지적했다. 다음으로, __init__.py테스트 디렉토리에 빈 파일을 넣으면 테스트 디렉토리가 패키지의 일부가됩니다. 그럼 당신은 할 수있을 것입니다

from ..components.core import GameLoopEvents

그러나 테스트 스크립트를 기본 프로그램으로 실행하면 다시 실패합니다. 테스트 러너를 사용하십시오. 어쩌면 이것은 다른 테스트 러너와도 작동 nosetests하지만 확인하지 않았습니다. 도움이 되었기를 바랍니다.


답변

내 빠른 해결책은 디렉토리를 경로에 추가하는 것입니다.

import sys
sys.path.insert(0, '../components/')