[python] __init__.py은 (는) 무엇 이죠?

__init__.py파이썬 소스 디렉토리의 내용은 무엇입니까 ?



답변

패키지의 필수 부분이되었습니다 ( 이전 3.3+ “네임 스페이스 패키지”가 아닌 3.3 이전 “일반 패키지” ).

여기 문서가 있습니다.

파이썬은 일반 패키지와 네임 스페이스 패키지라는 두 가지 유형의 패키지를 정의합니다. 일반 패키지는 Python 3.2 및 이전 버전에 존재했던 기존 패키지입니다. 일반 패키지는 일반적으로 __init__.py파일을 포함하는 디렉토리로 구현됩니다 . 일반 패키지를 가져 오면이 __init__.py파일이 내재적으로 실행되고 정의 된 객체가 패키지 네임 스페이스의 이름에 바인딩됩니다. __init__.py파일은 다른 모듈을 포함 할 수있는 동일한 파이썬 코드를 포함 할 수 있으며 가져올 때 파이썬 모듈에 몇 가지 추가 속성을 추가합니다.

그러나 링크를 클릭하면 예제, 추가 정보 및 네임 스페이스 패키지에 대한 설명, 패키지가없는 종류가 포함됩니다 __init__.py.


답변

명명 된 파일 __init__.py은 디스크의 디렉토리를 Python 패키지 디렉토리로 표시하는 데 사용됩니다. 파일이 있다면

mydir/spam/__init__.py
mydir/spam/module.py

mydir경로에, 당신의 코드를 가져올 수 module.py등을

import spam.module

또는

from spam import module

__init__.py파일 을 제거하면 Python은 더 이상 해당 디렉토리에서 하위 모듈을 찾지 않으므로 모듈 가져 오기 시도가 실패합니다.

__init__.py파일은 일반적으로 비어 있지만, 위의 예제 감안할 등을보다 편리 이름, 홀드 편의 기능에 따라 패키지의 선택된 부분을 수출하는 데 사용할 수 있습니다, 초기화 모듈의 내용은 다음과 같이 액세스 할 수 있습니다

import spam

이것을 기반으로


답변

파이썬 패키지와 디렉토리를 라벨 및 정의뿐만 아니라 __all__, __init__.py패키지 수준에서 어떤 변수를 정의 할 수 있습니다. 패키지가 API와 같은 방식으로 자주 가져올 항목을 정의하는 경우 편리합니다. 이 패턴은 Pythonic “평면이 중첩보다 낫다”라는 철학을 고수합니다.

다음은 내 프로젝트 중 하나의 예입니다 . 데이터베이스와 상호 작용하기 위해 자주 sessionmaker호출 Session을 가져옵니다 . 몇 가지 모듈로 “데이터베이스”패키지를 작성했습니다.

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

__init__.py코드는 다음과 같습니다.

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Session여기에서 정의 했으므로 아래 구문을 사용하여 새 세션을 시작할 수 있습니다. 이 코드는 “데이터베이스”패키지 디렉토리 내부 또는 외부에서 동일하게 실행됩니다.

from database import Session
session = Session()

물론 이것은 작은 편의성입니다. 대안은 Session데이터베이스 패키지의 “create_session.py”와 같은 새 파일에서 정의하고 다음 을 사용하여 새 세션을 시작하는 것입니다.

from database.create_session import Session
session = Session()

추가 자료

여기에 적절한 용도를 다루는 꽤 흥미로운 레딧 스레드가 __init__.py있습니다.

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

대다수의 견해 __init__.py는 “명시적인 것이 암시적인 것보다 낫다”는 철학을 위반하지 않도록 파일이 매우 얇아 야 한다는 것 같습니다 .


답변

두 가지 주요 이유가 있습니다 __init__.py

  1. 편의상 : 다른 사용자는 패키지 계층에서 함수의 정확한 위치를 알 필요가 없습니다.

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    # in file1.py
    def add():
        pass

    그런 다음 다른 사람들이 add ()를 호출하여

    from your_package import add

    file1을 모른 채

    from your_package.file1 import add
  2. 무언가를 초기화하고 싶다면; 예를 들어, 로깅 (최상위 레벨에 배치해야 함) :

    import logging.config
    logging.config.dictConfig(Your_logging_config)

답변

__init__.py파일은 파이썬이 그것을 포함하는 디렉토리를 모듈로 취급하게합니다.

또한이 파일은 모듈에 첫 번째로로드되는 파일이므로 모듈을로드 할 때마다 실행할 코드를 실행하거나 내보낼 하위 모듈을 지정할 수 있습니다.


답변

Python 3.3부터는 __init__.py더 이상 디렉토리를 가져 오기 가능한 Python 패키지로 정의 할 필요가 없습니다.

확인 PEP 420 : 암시 적 네임 스페이스 패키지 :

필요하지 않은 패키지 디렉토리에 대한 기본 지원 __init__.py마커 파일을 자동으로 여러 경로 세그먼트를 확장 할 수 (에 설명 된대로 다양한 타사에서 영감는 네임 스페이스 패키지에 접근 PEP 420 )

테스트는 다음과 같습니다.

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

참조 :
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
은 __init__입니다. Python 3의 패키지에는 py가 필요하지 않습니까?


답변

파이썬에서 패키지의 정의는 매우 간단합니다. Java와 마찬가지로 계층 구조와 디렉토리 구조는 동일합니다. 그러나 당신은 __init__.py패키지 에 있어야 합니다. __init__.py아래 예제를 통해 파일을 설명 하겠습니다.

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py존재하는 한 비어있을 수 있습니다. 디렉토리가 패키지로 간주되어야 함을 나타냅니다. 물론 __init__.py적절한 콘텐츠를 설정할 수도 있습니다.

module_n1에 함수를 추가하면 :

def function_X():
    print "function_X in module_n1"
    return

실행 후 :

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

그런 다음 계층 구조 패키지를 따르고 함수를 module_n1이라고했습니다. __init__.pysubPackage_b에서 다음과 같이 사용할 수 있습니다 :

__all__ = ['module_n2', 'module_n3']

실행 후 :

>>>from package_x.subPackage_b import *
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

따라서 * 가져 오기를 사용하면 모듈 패키지에 __init__.py내용 이 적용됩니다 .