프로그래밍 언어/Python

Python 3의 상대적 가져 오기

Rateye 2021. 12. 3. 08:38
728x90
반응형
질문 : Python 3의 상대적 가져 오기

같은 디렉토리의 다른 파일에서 함수를 가져오고 싶습니다.

from .mymodule import myfunction 과 함께 작동하지만 때로는 다음을 얻습니다.

SystemError: Parent module '' not loaded, cannot perform relative import

from mymodule import myfunction 과 함께 작동하지만 때로는 다음을 얻습니다.

SystemError: Parent module '' not loaded, cannot perform relative import

나는 여기서 논리를 이해하지 못하고 설명을 찾을 수 없습니다. 이것은 완전히 무작위로 보입니다.

누군가가이 모든 것의 논리가 무엇인지 설명해 주시겠습니까?

답변

안타깝게도이 모듈은 패키지 내부에 있어야하며 때로는 스크립트로도 실행 가능해야합니다. 내가 어떻게 이룰 수 있을지 아십니까?

이와 같은 레이아웃을 갖는 것은 매우 일반적입니다 ...

main.py
mypackage/
    __init__.py
    mymodule.py
    myothermodule.py

...이 같은 mymodule.py ...

#!/usr/bin/env python3

# Exported function
def as_int(a):
    return int(a)

# Test function for module  
def _test():
    assert as_int('1') == 1

if __name__ == '__main__':
    _test()

...이 같은 myothermodule.py

#!/usr/bin/env python3

from .mymodule import as_int

# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()

... 그리고 이와 같은 main.py

#!/usr/bin/env python3

from mypackage.myothermodule import add

def main():
    print(add('1', '1'))

if __name__ == '__main__':
    main()

main.py 또는 mypackage/mymodule.py 실행하면 제대로 작동하지만 상대 가져 오기로 인해 mypackage/myothermodule.py 실패합니다 ...

from .mymodule import as_int

실행해야하는 방식은 ...

python3 -m mypackage.myothermodule

#!/usr/bin/env python3 과 같은 shebang 라인과 잘 섞이지 않습니다.

이 경우에 대한 가장 간단한 수정은 mymodule 이름이 전역 적으로 고유하다고 가정하고 상대 가져 오기를 사용하지 않고 다음을 사용하는 것입니다.

from mymodule import as_int

... 독특하지 않거나 패키지 구조가 더 복잡한 경우 PYTHONPATH 패키지 디렉토리가 포함 된 디렉토리를 포함하고 다음과 같이 수행해야합니다.

from mypackage.mymodule import as_int

... 또는 "즉시"작동하도록 PYTHONPATH 먼저 코드에서 PYTHONPATH를 다음과 같이 만들 수 있습니다.

import sys
import os

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))

from mypackage.mymodule import as_int

일종의 고통이지만 특정 Guido van Rossum이 작성한 이메일에 이유에 대한 단서가 있습니다.

__main__ 기계의 다른 제안 된 트위들 링에 대해 -1입니다. 유일한 유스 케이스는 모듈의 디렉토리 안에있는 스크립트를 실행하는 것 같습니다. 저는 항상 안티 패턴으로 보았습니다. 제 마음을 바꾸려면 그렇지 않다는 것을 저를 설득해야합니다.

패키지 내에서 스크립트를 실행하는 것이 반 패턴인지 아닌지는 주관적이지만 개인적으로 사용자 정의 wxPython 위젯이 포함 된 패키지에서 정말 유용하다는 것을 알게 되었기 때문에 소스 파일에 대해 스크립트를 실행하여 wx.Frame 테스트 목적으로 해당 위젯 만 포함하는 wx.Frame

출처 : https://stackoverflow.com/questions/16981921/relative-imports-in-python-3
728x90
반응형