etc./StackOverFlow

__init__.py는 무엇을 위한 것입니까?

청렴결백한 만능 재주꾼 2021. 11. 9. 00:28
반응형

질문자 :Mat


Python 소스 디렉토리에서 __init__.py 는 무엇입니까?



이전에는 패키지의 필수 부분이었습니다( 이전, 3.3 이전 "일반 패키지" , 최신 3.3+ "네임스페이스 패키지" 아님).

여기 문서가 있습니다.

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

__init__.py 없는 패키지 종류인 네임스페이스 패키지에 대한 설명이 포함되어 있습니다.


Loki

__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 파일은 일반적으로 비어 있지만 더 편리한 이름으로 패키지의 선택된 부분을 내보내고, 편의 기능을 유지하는 등의 데 사용할 수 있습니다. 위의 예에서 init 모듈의 내용은 다음과 같이 액세스할 수 있습니다.

 import spam

에 따라


caritos

디렉토리에 Python 패키지로 레이블을 지정하고 __all__ __init__.py 사용하면 패키지 수준에서 모든 변수를 정의할 수 있습니다. 패키지가 API와 같은 방식으로 자주 가져올 항목을 정의하는 경우 그렇게 하는 것이 종종 편리합니다. 이 패턴은 Pythonic "flat is better than nested" 철학을 준수하도록 촉진합니다.

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

 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 정의하므로 아래 구문을 사용하여 새 세션을 시작할 수 있습니다. 이 코드는 "database" 패키지 디렉토리 내부 또는 외부에서 실행되는 것과 동일합니다.

 from database import Session session = Session()

물론 이것은 작은 편리함입니다. 대안은 내 데이터베이스 패키지의 "create_session.py"와 같은 새 파일에 Session

 from database.create_session import Session session = Session()

추가 읽기

__init__.py 적절한 사용을 다루는 꽤 흥미로운 reddit 스레드가 있습니다.

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

대다수 의견은 "명시적인 것이 암시적인 것보다 낫다"는 철학을 위반하지 않도록 __init__.py


Nathan Gould

__init__.py 에는 2가지 주요 이유가 있습니다.

  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)

flycee

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

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


Can Berk Güder

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/
Python 3의 패키지에는 __init__.py가 필요하지 않습니까?


zeekvfu

__init__.py 파일 없이 작동하지만 여전히 포함해야 합니다.

디렉토리가 패키지로 취급되어야 함을 지정하므로 이를 포함합니다(비어 있더라도).

__init__.py 파일을 사용할 수 있는 경우도 있습니다.

다음과 같은 파일 구조가 있다고 상상해보십시오.

 main_methods |- methods.py

그리고 methods.py 에는 다음이 포함되어 있습니다.

 def foo(): return 'foo'

foo() 를 사용하려면 다음 중 하나가 필요합니다.

 from main_methods.methods import foo # Call with foo() from main_methods import methods # Call with methods.foo() import main_methods.methods # Call with main_methods.methods.foo()

아마도 거기에 main_methods (예: 런타임/종속성) 안에 methods.py main_methods 있습니다.


methods.py 의 이름을 __init__.py main_methods 가져와서 foo() 를 사용할 수 있습니다.

 import main_methods print(main_methods.foo()) # Prints 'foo'

__init__.py 가 패키지의 일부로 취급되기 때문에 작동합니다.


일부 Python 패키지는 실제로 이 작업을 수행합니다. 예는 JSON을 사용하는 것입니다 . 여기서 import json 실행하면 실제로 json 패키지에서 __init__.py 를 가져옵니다(여기에서 패키지 파일 구조 참조 ).

소스 코드: Lib/json/__init__.py


Simon

Python에서 패키지의 정의는 매우 간단합니다. 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 함수를 호출했습니다. 다음과 같이 subPackage_b에서 __init__.py 를 사용할 수 있습니다.

 __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 내용이 적용됩니다.


Marcus Thornton

__init__.py 는 해당 디렉토리를 로드 가능한 모듈로 취급합니다.

코드 읽기를 선호하는 사람들을 위해 여기에 Two-Bit Alchemist의 설명을 넣었습니다.

 $ find /tmp/mydir/ /tmp/mydir/ /tmp/mydir//spam /tmp/mydir//spam/__init__.py /tmp/mydir//spam/module.py $ cd ~ $ python >>> import sys >>> sys.path.insert(0, '/tmp/mydir') >>> from spam import module >>> module.myfun(3) 9 >>> exit() $ $ rm /tmp/mydir/spam/__init__.py* $ $ python >>> import sys >>> sys.path.insert(0, '/tmp/mydir') >>> from spam import module Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named spam >>>

B.Mr.W.

다른 파이썬 파일을 쉽게 가져올 수 있습니다. 이 파일을 다른 py 파일을 포함하는 디렉토리(예: 물건)에 배치하면 import stuff.other와 같은 작업을 수행할 수 있습니다.

 root\ stuff\ other.py morestuff\ another.py

디렉토리 물건 안에 이 __init__.py 없으면 other.py를 가져올 수 없습니다. 파이썬은 물건의 소스 코드가 어디에 있는지 모르고 그것을 패키지로 인식할 수 없기 때문입니다.


Epitaph

__init__.py 파일을 사용하면 쉽게 가져올 수 있습니다. __init__.py 가 패키지 내에 b.py 과 같이 a() 를 가져올 수 있습니다.

 from b import a

그러나 이것이 없으면 직접 가져올 수 없습니다. 시스템 경로를 수정해야 합니다.

 import sys sys.path.insert(0, 'path/to/b.py') from b import a

Alec

__init__.py가 허용하는 한 가지는 API를 중단하거나 관련 없는 중첩된 네임스페이스 또는 개인 모듈*을 생성하지 않고 모듈을 패키지로 변환하는 것입니다. 이것은 네임스페이스를 확장하고 싶을 때 도움이 됩니다.

다음을 포함하는 util.py 파일이 있는 경우

 def foo(): ...

그러면 사용자는 다음을 사용하여 foo 에 액세스합니다.

 from util import foo

그런 다음 데이터베이스 상호 작용을 위한 유틸리티 기능을 추가하고 util 아래에 고유한 네임스페이스를 갖기를 원하면 새 디렉토리**가 필요하고 API 호환성을 유지하기 위해 ( from util import foo 계속 작동하도록), 나는 그것을 util/이라고 부를 것이다. util.py를 util/로 이동할 수 있습니다.

 util/ __init__.py util.py db.py

util/__init__.py에서

 from util import *

그러나 이것은 중복됩니다. util/util.py 파일 대신 util.py 내용을 __init__.py에 넣으면 사용자는 이제

 from util import foo from util.db import check_schema

util util 모듈과 유사한 방식으로 작동하는 방식을 훌륭하게 강조한다고 생각합니다.

* 이것은 다른 답변에 암시되어 있지만 여기에서 강조하고 싶습니다.
** 수입 체조 채용 부족. 파일과 동일한 이름으로 새 패키지를 생성하는 것은 작동하지 않습니다. 이것을 참조하십시오.


joel

출처 : http:www.stackoverflow.com/questions/448271/what-is-init-py-for

반응형