복붙노트

[PYTHON] 모듈 가져 오기 : __main__ 대 모듈 가져 오기

PYTHON

모듈 가져 오기 : __main__ 대 모듈 가져 오기

머리말을하기 위해이 코드를 가져 오는 방법 (가져온 후에 모듈 변수를 변경하는 방법을 기반으로)을 얻는 방법을 찾은 것 같지만 다음 질문이 실제로 발생하는 이유는 무엇인가에 대해 이해할 수 있습니다.

3 개의 파일이 있습니다. 첫 번째는 mod1.py입니다.

# mod1.py

import mod2

var1A = None

def func1A():
    global var1
    var1 = 'A'
    mod2.func2()

def func1B():
    global var1
    print var1

if __name__ == '__main__':
    func1A()

다음으로 mod2.py가 있습니다.

# mod2.py

import mod1

def func2():
    mod1.func1B()

마지막으로 driver.py :

# driver.py

import mod1

if __name__ == '__main__':
    mod1.func1A()

python mod1.py 명령을 실행하면 출력은 None입니다. 위에서 언급 한 링크를 기반으로, mod2.py에서 가져 오는 mod1.py와 __main__으로 가져 오는 mod1.py 사이에는 약간의 차이가있는 것으로 보입니다. 따라서 driver.py를 만들었습니다. python driver.py 명령을 실행하면 예상되는 결과를 얻을 수 있습니다. A. 일종의 차이점을 볼 수는 있지만 실제로 메커니즘이나 그 이유는 알 수 없습니다. 어떻게 그리고 왜 이런 일이 발생합니까? 똑같은 모듈이 두 번 존재한다는 것은 반 직관적 인 것처럼 보인다. 파이썬 mod1.py를 실행하면 mod2.py에서 가져온 버전의 변수 대신 mod1.py의 __main__ 버전의 변수에 액세스 할 수 있습니까?

해결법

  1. ==============================

    1.__name__ 변수는 파일이 인터프리터에 스크립트로로드 된 경우를 제외하고 항상 모듈의 이름을 포함합니다. 그 변수는 대신 '__main__'문자열로 설정됩니다.

    __name__ 변수는 파일이 인터프리터에 스크립트로로드 된 경우를 제외하고 항상 모듈의 이름을 포함합니다. 그 변수는 대신 '__main__'문자열로 설정됩니다.

    결국 스크립트는 전체 프로그램의 주 파일로 실행되고, 그 밖의 모든 모듈은 해당 주 파일에 의해 직접 또는 간접적으로 가져옵니다. __name__ 변수를 테스트하면 파일을 모듈로 가져 왔는지 또는 직접 실행했는지 감지 할 수 있습니다.

    내부적으로 모듈에는 sys.modules의 각 모듈에 대한 메타 데이터의 일부로 저장된 네임 스페이스 사전이 제공됩니다. 실행 된 스크립트 인 주 파일은 '__main__'과 동일한 구조로 저장됩니다.

    하지만 파일을 모듈로 가져올 때, 파이썬은 먼저 sys.modules를보고 그 모듈이 이미 이전에 가져 왔는지 확인합니다. 따라서 import mod1은 sys1.modules에서 mod1 모듈을 먼저 찾습니다. mod1이 아직 없으면 네임 스페이스가있는 새로운 모듈 구조가 생성됩니다.

    따라서 mod1.py를 주 파일로 실행하고 나중에 python 모듈로 가져 오면 sys.modules에 두 개의 네임 스페이스 항목이 생깁니다. 하나는 '__main__', 나중에는 'mod1'입니다. 이 두 네임 스페이스는 완전히 별개입니다. 전역 var1은 sys.modules [ '__ main__']에 저장되지만 func1B는 sys.modules [ 'mod1']에서 var1을 찾고 있습니다 (None 인 경우).

    그러나 python driver.py를 사용하면 driver.py는 프로그램의 '__main__'주 파일이되고 mod1은 sys.modules [ 'mod1'] 구조로 한 번만 가져옵니다. 이번에는 func1A가 var1을 sys.modules [ 'mod1'] 구조체에 저장하고 func1B가 찾을 것입니다.

  2. ==============================

    2.선택적으로 주 스크립트로 모듈을 사용하기위한 실질적인 솔루션 - 일관된 교차 - 가져 오기 지원 :

    선택적으로 주 스크립트로 모듈을 사용하기위한 실질적인 솔루션 - 일관된 교차 - 가져 오기 지원 :

    예 : 파이썬 pdb 모듈에서, __main__ (결국)으로 실행할 때 자신을 임포트하여 스크립트로 실행하는 방법 :

    #! /usr/bin/env python
    """A Python debugger."""
    # (See pdb.doc for documentation.)
    import sys
    import linecache
    
    ...
    
    # When invoked as main program, invoke the debugger on a script
    if __name__ == '__main__':
        import pdb
        pdb.main()
    

    __main__ 시작을 다음과 같이 스크립트 시작 부분으로 재구성하는 것이 좋습니다.

    #! /usr/bin/env python
    """A Python debugger."""
    # When invoked as main program, invoke the debugger on a script
    import sys
    if __name__ == '__main__':        
        ##assert os.path.splitext(os.path.basename(__file__))[0] == 'pdb'
        import pdb
        pdb.main()
        sys.exit(0)
    
    import linecache
    ...
    

    이렇게하면 모듈 본체가 두 번 실행되지 않습니다. 이는 "비용이 많이 드는", 바람직하지 않으며 때로는 중요합니다.

    드문 경우에는 실제 모듈 별명 (mod1)으로 직접 실제 스크립트 모듈 __main__을 노출하는 것이 바람직합니다.

    # mod1.py    
    import mod2
    
    ...
    
    if __name__ == '__main__':
        # use main script directly as cross-importable module 
        _mod = sys.modules['mod1'] = sys.modules[__name__]
        ##_modname = os.path.splitext(os.path.basename(os.path.realpath(__file__)))[0]
        ##_mod = sys.modules[_modname] = sys.modules[__name__]
        func1A()
    

    알려진 단점 :

  3. from https://stackoverflow.com/questions/13181559/importing-modules-main-vs-import-as-module by cc-by-sa and MIT license