__init__.py에 코드 추가


85

장고의 모델 시스템이 어떻게 작동하는지 살펴보고 있는데 이해가 안되는 부분을 발견했습니다.

__init__.py현재 디렉터리가 패키지임을 지정하기 위해 빈 파일을 만드는 것을 알고 있습니다 . 그리고 __init__.pyimport *가 제대로 작동하도록 몇 가지 변수를 설정할 수 있습니다 .

그러나 django는 from ... import ... 문을 추가하고 __init__.py. 왜? 이것은 단지 일을 지저분하게 보이게하지 않습니까? 이 코드가 필요한 이유가 __init__.py있습니까?


13
이것은 장고에 관한 것이 아닙니다. 예, Django에서 처음 보았지만 이것은 순수한 Python처럼 보입니다. Django 태그가 실제로 적절하지 않을 수도 있습니다.
S.Lott

__init__.pydjango 1.8 에서 import 문을 볼 수 없습니다 . 이전 버전 이었나요? 그렇다면 어떤 버전입니까?
Gobi Dasu

답변:


72

__init__.py포함 된 패키지 (디렉토리)를 가져올 때 모든 가져 오기를 사용할 수 있습니다.

예:

./dir/__init__.py:

import something

./test.py:

import dir
# can now use dir.something

편집 : 언급하는 것을 잊었습니다 __init__.py. 해당 디렉토리에서 모듈을 처음 가져올 때 코드가 실행됩니다. 따라서 일반적으로 패키지 수준 초기화 코드를 넣는 것이 좋습니다.

EDIT2 : dgrant는 내 예에서 가능한 혼란을 지적했습니다. In __init__.py import something은 패키지에서 필요하지 않은 모든 모듈을 가져올 수 있습니다. 예를 들어으로 바꿀 수 있습니다 import datetime. 그러면 최상위 수준 test.py에서 다음 코드 조각이 모두 작동합니다.

import dir
print dir.datetime.datetime.now()

import dir.some_module_in_dir
print dir.datetime.datetime.now()

결론은 다음과 같습니다. __init__.py가져온 모듈, 함수 또는 클래스에 관계없이에 할당 된 모든 이름 은 패키지 또는 패키지의 모듈을 가져올 때마다 패키지 네임 스페이스에서 자동으로 사용할 수 있습니다.


괜찮 감사. 그러나 나는 클래스를 추가하는 것이 왜 좋은 생각인지 잘 모르겠습니다. __init__.py 이러한 클래스 초기화 코드를 실제로 고려하지 않습니다.
Erik

패키지로 작업 할 때마다 유용한 클래스 일 것입니다. 하지만 추측하고 싶지 않습니다. 그들이 거기에있는 이유는 객관적이든
아니든

13
이것은 또한 역사적인 이유 때문일 수 있습니다. 모듈을 패키지로 변환 할 때 module.py를 module / __ init__.py로 기존의 모든 코드에서 이전과 같이 사용할 수 있지만 이제 모듈은 하위 모듈을 가질 수 있습니다.
Łukasz

1
모듈은 부모를 __init__.py암시 적으로 실행 합니다. 에서 모듈을 가져 오면 __init__.py주기적인 가져 오기가 생성됩니다. 은 __init__.py완전히 하나 개의 가져 오기 전에 실행되지 않습니다. __init__.py비워 두는 것이 더 안전합니다 .
Ivo Danihelka 2010

이것은 __init__.py파일 에만 국한되지 않는다는 점에 주목하는 것이 중요 합니다. 당신이 파일이 있다면 dir/other.py무엇인가가 있었다처럼 from datetime import datetime당신은 또한 전화를 할 수있을 것입니다 dir.other.datetime.now()심지어 나 from dir.other import datetime.
칼 레스 살라

37

그것은 실제로 개인적인 취향이며 파이썬 모듈의 레이아웃과 관련이 있습니다.

라는 모듈이 있다고 가정 해 보겠습니다 erikutils. 거기는 모듈 될 수 있다는 두 가지 방법이 있습니다, 하나는라는 파일이 erikutils.py을 당신에 sys.path또는 당신이라는 디렉토리가 erikutils 온을 sys.path빈과 __init__.py그 안에 파일. 그럼 당신이 전화 모듈의 무리가 있다고 가정하자 fileutils, procutils, parseutils그리고 당신이 그 미만의 서브 모듈이되고 싶어요 erikutils. 따라서 fileutils.py , procutils.pyparseutils.py 라는 .py 파일을 만듭니다 .

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

어쩌면 당신은하지에 속하지 않는 몇 가지 기능을 가지고 fileutils, procutils또는 parseutils모듈을. 라는 새 모듈을 만들고 싶지 않다고 가정 해 보겠습니다 miscutils. 그리고 다음과 같이 함수를 호출 할 수 있기를 원합니다.

erikutils.foo()
erikutils.bar()

하기보다는

erikutils.miscutils.foo()
erikutils.miscutils.bar()

그래서 erikutils모듈은 파일이 아니라 디렉토리 이기 때문에 우리는 내부에 함수를 정의해야합니다.__init__.py 합니다.

장고에서 내가 생각할 수있는 가장 좋은 예는 django.db.models.fields. 모든 django * Field 클래스는 django / db / models / fields 디렉토리 의 __init__.py파일에 정의되어 있습니다 . 나는 그들이 가상으로 학원의 모든 것을 원하지 않았기 때문에 그들이 이런 짓을 생각 장고 / DB / 모델 / fields.py 모델들은 (몇 서브 모듈로를 분할 있도록 related.py , files.py 예를 들어,)와 그들은 만들어진 * Field 정의를 fields 모듈 자체에 붙였습니다 (따라서 __init__.py).


1
dgrant, 내가 의미 something하는 것은 외부 모듈 이 될 수 있다는 것입니다. dir.something은 제대로 작동합니다. 의견을 보내 주셔서 감사합니다. 게시물을 더 명확하게 수정하겠습니다.
Alexander Kojevnikov

29

사용 __init__.py 파일하면 외부에서 내부 패키지 구조 보이지 않게 할 수 있습니다. 내부 구조가 변경되면 (예 : 하나의 지방 모듈을 두 개로 분할하기 때문에)__init__.py 파일 되지만 패키지에 의존하는 코드는 되지 않습니다. 예를 들어 일반적으로 사용할 준비가되지 않은 경우 패키지의 일부를 보이지 않게 만들 수도 있습니다.

del명령을 사용할 수 있으므로 일반적인 __init__.py것은 다음과 같습니다.

from somemodule import some_function1, some_function2, SomeObject

del somemodule

이제 분할하기로 결정한 경우 somemodule새 항목 __init__.py은 다음과 같습니다.

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

외부에서 보면 패키지는 여전히 이전과 동일하게 보입니다.


1
@Arlen : 요점은 공개 API의 일부가 아니라는 것입니다. 모듈의 이름을 바꾸면 종속 코드가 깨지지 않도록 할 수 있습니다. 또한 API 문서를 자동으로 생성하기 위해 인트로 스펙 션을 사용할 때와 같이 API 요소가 한 번만 표시되도록합니다.
nikow

5
@Arlen : 모듈을 삭제하면 모듈이 import <pack>.somemodule1직접적으로 차단 됩니다. <pack>해당 __init__.py및 삭제되지 않은 하위 모듈 에서 정의되거나 가져온 개체 에서만 가져올 수 있습니다 .
MestreLion 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.