ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 모듈 Module과 __main__
    코딩/Python 2022. 12. 20. 23:29
    728x90

    Module

    Import module & namespace

    • 모듈: 외부에서 임포트해서 쓰는 라이브러리 같은 함수들의 컬렉션
    • 외부 모듈을 임포트할 때 파이썬은 모듈의 함수들을 직접 가지고 오지 않고 모듈 이름만 현재의 'namespace'에 추가
    • 이 모듈의 이름은 전역변수 __name__ 에 저장
    • 모듈의 함수는 모듈이름.함수()로 호출.
    • 자주 쓰는 함수는 다른 이름으로 대입해서 사용.
    # 외부 모듈 my_func.py
    def func_a():
      print(a)
    def func_b():
      print(b)
    import my_func
    
    my_func.func_a()
    my_func.func_b()
    
    func_c = my_func.func_a
    func_c()
    • 각 모듈에는 정의된 모든 함수들에 의해 전역 namespace로 사용되는 고유한 namespace가 있다.
    • 모듈은 다른 모듈을 임포트할 수 있다. 임포트하는 모듈의 namspace에 직접적으로 모듈에서 이름을 임포트하는 임포트문의 변형.
    from my_func import func_a, func_b
    func_a()

    모듈이 정의하는 모든 이름을 임포트하는 변형

    from my_func import *
    func_a()
    • 밑줄 (_) 로 시작하는 것들을 제외한 모든 이름을 임포트
    • 가능한 사용하지 않은 것이 좋음

    모듈 이름 다음에 as 가 올 경우, as 다음의 이름을 임포트한 모듈에 직접 연결

    import my_func as mf
    mf.func_a()
    from my_func import func_a as fa
    fa()

    Module as script

    if __name__ == '__main__': 로 시작하는 코드를 붙여 스크립트처럼 사용될 때 별도로 실행되는 모듈을 만들 수 있다.

    # 외부 모듈 new_my_func.py
    def func_a(a):
        print(a)
    def func_b():
        print(b)
    
    if __name__ == '__main__':
        import sys
        func_a(str(sys.argv[1]))
    >>> python new_my_func.py 'aaa'
    'aaa'

    __main__ top level code environment

    두가지 중요한 구조를 위해 특별한 이름 __main__ 이 사용.

    • __name__ == '__main__' 표현으로 확인할 수 있는 프로그램의 최상위레벨의 이름
    • 파이썬 패키지의 __main__.py 파일
      사용자가 어떻게 이들과 상호작용을 할 수 있는지, 그리고 어떻게 그들이 서로 상호작용하는지, 이들 메카니즘 모두 파이썬 모듈과 연관

    __name__ == '__main__'

    • 파이썬 모듈이나 패키지가 임포트될 때, __name__ 은 모듈의 이름이 지정
    • 보통은 .py 확장자가 붙지않은 파일 이름 그 자체가 된다
    import configparser
    configparser.__name__
    'configparser'

    만일 파일이 한 패키지의 부분이라면, __name__ 은 또한 부모 패키지의 경로를 포함.

    from concurrent.futures import process
    process.__name__
    'concurrent.futures.process'

    최상위 코드 환경

    • __main__은 최상위 코드가 실행되는 환경의 이름
    • '최상위 코드'는 실행이 시작되는 첫번째 사용자 지정 파이썬 모듈
    • 프로그램이 필요로 하는 모든 다른 모듈을 최상위 코드가 임포트하기 때문에 '최상위'
    • 때때로 '최상위 코드'는 어플리케이션으로의 입구지점이라 불림

    최상위 코드 환경:

    the scope of an interactive prompt:

    >>> __name__
    '__main__'

    인터프리터에게 파일 인자로 파이썬 모듈을 전달:

    >>> python3 helloworld.py  
    Hello, world!

    인터프리터에게 -m 인수와 함께 모듈 또는 패키지를 전달

    python3 -m tarfile  
    usage: tarfile.py \[-h\] \[-v\] (...)

    표준 입력으로부터 파이썬 인터프리터에게 읽혀진 파이썬 코드

    echo "import this" | python3  
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.  
    Explicit is better than implicit.  
    ...

    -c 인수와 함께 파이썬 인터프리터로 넘겨진 파이썬 코드

    python3 -c "import this"  
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.  
    Explicit is better than implicit.  
    ...

    이들 상황에서, 최상위 모듈의 __name____main__ 으로 설정된다.

    결과로, 모듈은 자신의 __name__을 확인함으로써 최상위 환경에서 실행하는지 아닌지를 알 수 있다.
    이는 모듈이 임포트문으로부터 초기화되지 않을 때 조건부로 실행하기 위한 일반적인 관용구를 허용한다.

    if `__name__ == '__main__'`:  
    
    # Execute when the module is not initialized from an import statement.

    관용적인 사용법

    어떤 모듈들은 명령줄 인수 구문 분석 또는 표준 입력에서 데이터 가져오기와 같이 의도적으로 스크립트로만 사용하도록 되어 있다.
    이와 같은 모듈이 다른 모듈로부터 임포트되었다면, 예를 들어 유니트 테스트를 위해, 스크립트 코드는 또한 의도하지 않게 실행될 것이다.

    이것이 if __name__ == '__main__' 코드블럭이 편리한 점이다.
    이 블럭 안의 코드는 모듈이 최상위에서 실행되지 않는다면 구동되지 않는다.

    if __name__ == '__main__' 아래 블럭에 가능한 한 적은 문장들을 두면 코드의 명확성과 정확성이 향상될 수 있다.
    대부분의 경우 메인이라 이름의 함수는 프로그램의 기본 동작을 함수화한다.

    # echo.py
    
    import shlex
    import sys
    
    def echo(phrase: str) -> None:
       """A dummy wrapper around print."""
       # for demonstration purposes, you can imagine that there is some
       # valuable and reusable logic inside this function
       print(phrase)
    
    def main() -> int:
        """Echo the input arguments to standard output"""
        phrase = shlex.join(sys.argv)
        echo(phrase)
        return 0
    
    if __name__ == '__main__':
        sys.exit(main())  # next section explains the use of sys.exit

    만일 모듈이 메인 함수 내에서 코드를 캡슐화하지 않고 대신 if __name__ == '__main__' 블럭에 직접적으로 뒀다면, 구문 변수는 전체 모듈에서 전역적이다.
    이것은 모듈내의 다른 함수들이 로컬 이름 대신 전역변수가 의도치 않게 사용되는 에러가 발생하기 쉽다.
    메인 함수는 이런 문제를 해결한다.

    메인함수를 사용함으로써 echo 기능 자체가 격리되고 다른 곳에서 가져올 수 있다는 추가적인 이점을 가진다.
    echo.py가 임포트될 때, echo와 main 함수는 정의될 것이다. 그러나 둘다 호출되지는 않는다.
    __name__ != '__main__' 이기 때문이다.

    728x90

    댓글

Designed by Tistory.