답변:
로 해석되는 해당 모듈의 공용 객체 목록입니다 import *
. 밑줄로 시작하는 모든 항목을 숨기는 기본값을 무시합니다.
import *
(예를 들어 tk
) 당신이 설계된 것으로 알고있는 모듈 만 가져 오는 것이 좋습니다 . 이 경우 __all__
모듈 코드에 밑줄로 시작하거나 이름 이있는 것이 좋은 힌트 입니다.
tk
오늘 (또는 2012 년에도) 출시 된 경우 권장되는 방법을 사용하는 것이 확실하지 않습니다 from tk import *
. 연습은 의도적 인 디자인이 아니라 관성으로 인해 받아 들여 졌다고 생각합니다.
여기에 명시 적으로 언급되지 않은 링크는 정확히 언제 __all__
사용 되는지 입니다. 모듈에서 from <module> import *
사용될 때 어떤 심볼을 내보낼 지 정의하는 문자열 목록입니다 .
예를 들어, 다음 코드 foo.py
를 명시 적으로는 기호 수출 bar
과 baz
:
__all__ = ['bar', 'baz']
waz = 5
bar = 10
def baz(): return 'baz'
그런 다음이 기호를 다음과 같이 가져올 수 있습니다.
from foo import *
print(bar)
print(baz)
# The following will trigger an exception, as "waz" is not exported by the module
print(waz)
경우 __all__
위의이 주석의 기본 동작은,이 코드는 완료 될 때까지 실행됩니다 import *
주어진 공간에서, 밑줄로 시작하지 않는 모든 기호를 가져 오는 것입니다.
참조 : https://docs.python.org/tutorial/modules.html#importing-from-a-package
참고 : 동작에만 __all__
영향을줍니다 from <module> import *
. 언급되지 않은 멤버 __all__
는 여전히 모듈 외부에서 액세스 할 수 있으며로 가져올 수 있습니다 from <module> import <member>
.
print(baz())
됩니까?
print(baz)
같은 것을 인쇄 <function baz at 0x7f32bc363c10>
반면 print(baz())
인쇄baz
파이썬에서 __all__을 설명 하시겠습니까?
__all__
다른__init__.py
파일에 변수 세트가 계속 표시 됩니다.이것은 무엇을 하는가?
__all__
합니까?모듈에서 의미 적으로 "공용"이름을 선언합니다. 에 이름이 있으면 __all__
사용자 는 해당 이름 을 사용해야하며 변경되지 않을 것으로 기대할 수 있습니다.
또한 프로그래밍 방식으로 영향을 미칩니다.
import *
__all__
모듈에서, 예 module.py
:
__all__ = ['foo', 'Bar']
수단이 때 import *
모듈에서의의 이름 만이 __all__
가져올 수 있습니다 :
from module import * # imports foo and Bar
문서 및 코드 자동 완성 도구는 __all__
모듈에서 사용 가능한 것으로 표시되는 이름을 결정하기 위해 실제로 검사해야 할 수도 있습니다.
__init__.py
디렉토리를 파이썬 패키지로 만든다로부터 문서 :
__init__.py
파일은 파이썬 치료 패키지가 들어있는 같은 디렉토리를 만들기 위해 필요합니다; 이는 문자열과 같은 공통 이름을 가진 디렉토리가 나중에 모듈 검색 경로에서 발생하는 유효한 모듈을 실수로 숨기지 않도록하기 위해 수행됩니다.가장 간단한 경우
__init__.py
빈 파일 일 수 있지만 패키지의 초기화 코드를 실행하거나__all__
변수를 설정할 수도 있습니다.
그래서이 __init__.py
을 선언 할 수 있습니다 __all__
A의 패키지 .
패키지는 일반적으로 서로 가져올 수 있지만 반드시 __init__.py
파일 과 함께 묶인 모듈로 구성 됩니다. 이 파일은 디렉토리를 실제 파이썬 패키지로 만듭니다. 예를 들어, 패키지에 다음 파일이 있다고 가정하십시오.
package
├── __init__.py
├── module_1.py
└── module_2.py
파이썬으로이 파일들을 만들어 보도록하겠습니다. 다음을 파이썬 3 셸에 붙여 넣을 수 있습니다 :
from pathlib import Path
package = Path('package')
package.mkdir()
(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")
package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")
package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")
이제 다른 사람이 패키지를 가져올 때 사용할 수있는 완전한 API를 제시했습니다.
import package
package.foo()
package.Bar()
그리고 패키지에는 package
네임 스페이스를 어지럽히는 모듈을 만들 때 사용한 다른 구현 세부 정보가 모두 없습니다 .
__all__
에 __init__.py
더 많은 작업을 한 후에는 모듈이 너무 커서 (수천 줄과 같이) 분할해야한다고 결정했을 수 있습니다. 따라서 다음을 수행하십시오.
package
├── __init__.py
├── module_1
│ ├── foo_implementation.py
│ └── __init__.py
└── module_2
├── Bar_implementation.py
└── __init__.py
먼저 모듈과 동일한 이름으로 서브 패키지 디렉토리를 만드십시오.
subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()
구현을 이동하십시오.
package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')
각각에 대해 __init__.py
선언하는 서브 패키지에 대해 s를 작성 하십시오 __all__
.
(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")
그리고 지금 당신은 여전히 패키지 수준에서 API를 프로비저닝했습니다.
>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>
또한 서브 패키지의 모듈 레벨 대신 서브 패키지 레벨에서 관리 할 수있는 것을 API에 쉽게 추가 할 수 있습니다. API에 새 이름을 추가하려면 간단히 __init__.py
예를 들어 module_2에서을 업데이트하십시오 .
from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']
Baz
최상위 API 로 게시 할 준비가되지 않은 경우 최상위 레벨에서 다음을 수행 __init__.py
할 수 있습니다.
from .module_1 import * # also constrained by __all__'s
from .module_2 import * # in the __init__.py's
__all__ = ['foo', 'Bar'] # further constraining the names advertised
사용자가의 가용성을 알고 있으면 다음 Baz
을 사용할 수 있습니다.
import package
package.Baz()
그러나 그들이 그것에 대해 모른다면 다른 도구 ( pydoc 같은 )는 그들에게 알리지 않을 것입니다.
나중에 Baz
프라임 타임 준비가 완료 되면 변경할 수 있습니다 .
from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']
_
대 __all__
:기본적으로 Python은로 시작하지 않는 모든 이름을 내 보냅니다 _
. 확실히이 메커니즘에 의존 할 수 있습니다. 파이썬 표준 라이브러리의 일부 패키지는, 사실, 할 이에 의존하지만, 예를 들어, 자신의 수입 별명 그래서 그들은을 위해 ctypes/__init__.py
:
import os as _os, sys as _sys
이 _
규칙을 사용하면 이름을 다시 지정하는 중복성이 제거되므로 더 우아 할 수 있습니다. 그러나 수입에 대한 중복성을 추가하고 (많은 수입이있는 경우) 이 일관된 작업을 잊어 버리기 쉽습니다 . 마지막으로 원하는 것은 구현 세부 사항 만 의도 한 것을 무기한으로 지원해야합니다. _
함수 이름 을 지정할 때 접두사를 잊어 버렸기 때문 입니다.
나는 __all__
내 코드를 사용하는 다른 사람들이 사용하고 사용하지 않아야 할 것을 알 수 있도록 개발 라이프 사이클 초기에 모듈에 대한 초기 글을 씁니다 .
표준 라이브러리에있는 대부분의 패키지도 사용 __all__
합니다.
__all__
차종의 의미다음 _
대신에 접두사 규칙 을 따르는 것이 합리적 입니다 __all__
.
export
장식사용의 단점은 __all__
두 번 내보내는 함수 및 클래스 이름을 작성해야하며 정보는 정의와 별도로 유지된다는 것입니다. 우리는 수 이 문제를 해결하기 위해 장식을 사용합니다.
나는 David Beazley의 포장에 관한 이야기에서 그런 수출 데코레이터에 대한 아이디어를 얻었다. 이 구현은 CPython의 기존 수입 업체에서 잘 작동하는 것 같습니다. 특별한 가져 오기 후크 또는 시스템이있는 경우 보증하지 않지만이를 채택하는 경우에는 취소하기가 쉽지 않습니다. 이름을 수동으로 다시 추가하면됩니다.__all__
예를 들어 유틸리티 라이브러리에서 데코레이터를 정의합니다.
import sys
def export(fn):
mod = sys.modules[fn.__module__]
if hasattr(mod, '__all__'):
mod.__all__.append(fn.__name__)
else:
mod.__all__ = [fn.__name__]
return fn
그런 다음을 정의하는 위치 __all__
에서 다음을 수행하십시오.
$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.
@export
def foo(): pass
@export
def bar():
'bar'
def main():
print('main')
if __name__ == '__main__':
main()
그리고 이것은 메인으로 실행되거나 다른 기능으로 가져 오더라도 잘 작동합니다.
$ cat > run.py
import main
main.main()
$ python run.py
main
API 프로비저닝 import *
도 작동합니다.
$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported
$ python run.py
Traceback (most recent call last):
File "run.py", line 4, in <module>
main() # expected to error here, not exported
NameError: name 'main' is not defined
__init__.py
이었습니다.__all__
__all__
올바른지 확인할 필요없이 제거하려는 기호에 많은 균열이있는 생성 된 파일이라는 것 입니다.
__all__
하지만 불안정한 API가 있다고 말할 것입니다 ... 이것은 포괄적 인 수용 테스트를해야 할 것입니다.
module_1
과 module_2
; 그것은 명시 적으로 포함 OK입니다 del module_1
에서를 __init__.py
? 이것이 가치 있다고 생각하는 것이 잘못입니까?
나는 이것을 정확하게 추가하고 있습니다.
다른 모든 답변은 모듈을 나타 냅니다. 파일에 명시 적으로 언급 __all__
된 원래 질문 __init__.py
이므로 파이썬 패키지 에 관한 것 입니다.
일반적으로 명세서 __all__
의 from xxx import *
변형 import
이 사용될 때만 작동합니다 . 이것은 패키지뿐만 아니라 모듈에도 적용됩니다.
모듈의 동작은 다른 답변에 설명되어 있습니다. 패키지의 정확한 동작은 여기 에 자세히 설명되어 있습니다 .
간단히 말해서 __all__
패키지 레벨에서 모듈 내에서 이름 을 지정하는 것과 달리 패키지 내 모듈 을 처리한다는 점을 제외하면 모듈과 거의 동일합니다 . 따라서 __all__
우리가 사용할 때 현재 네임 스페이스로로드 및 임포트 될 모든 모듈을 지정합니다 from package import *
.
가장 큰 차이점은 패키지에서 의 선언 을 생략 하면 명령문 이 아무것도 가져 오지 않는다는 것입니다 (문서에 설명 된 예외는 위의 링크 참조).__all__
__init__.py
from package import *
반면에 __all__
모듈에서 생략 하면 "별표 가져 오기"는 모듈에 정의 된 모든 이름 (밑줄로 시작하지 않음)을 가져옵니다.
from package import *
에 정의 __init__.py
되지 않은 모든 항목을 가져옵니다 all
. 중요한 차이점은 __all__
패키지 디렉토리에 정의 된 모듈을 자동으로 가져 오지 않는다는 것입니다.
또한 pydoc이 표시 할 내용을 변경합니다.
module1.py
a = "A"
b = "B"
c = "C"
module2.py
__all__ = ['a', 'b']
a = "A"
b = "B"
c = "C"
pydoc 모듈 1
모듈 module1에 대한 도움말 : 이름 모듈 1 파일 module1.py DATA = 'A' , B = 'B' C = 'C'
pydoc 모듈 2
모듈 module2에 대한 도움말 : 이름 모듈 2 파일 module2.py DATA __all__ = 'A', 'B'] = 'A' , B = 'B'
나는 __all__
내 모든 세부 사항뿐만 아니라 밑줄 내부 세부 사항을 선언 합니다. 이것은 실시간 통역 세션에서 전에 사용하지 않은 것을 사용할 때 실제로 도움이됩니다.
__all__
사용자 정의 *
에from <module> import *
__all__
사용자 정의 *
에from <package> import *
모듈 A는 .py
가져올 수 의미 파일.
패키지는 기호가있는 디렉토리 __init__.py
파일입니다. 패키지는 일반적으로 모듈을 포함합니다.
""" cheese.py - an example module """
__all__ = ['swiss', 'cheddar']
swiss = 4.99
cheddar = 3.99
gouda = 10.99
__all__
인간에게 모듈 의 "공개"기능을 알려줍니다 . [ @AaronHall ] 또한 pydoc 은이를 인식합니다. [ @ 롱 포크 ]
방법 swiss
과 cheddar
로컬 네임 스페이스로 가져 오는 방법을 참조하십시오 gouda
.
>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined
이 없으면 __all__
밑줄로 시작하지 않는 모든 기호를 사용할 수 있습니다.
*
은__all__
>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)
>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)
>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)
에서 __init__.py
의 파일 패키지 __all__
공공 모듈 또는 다른 개체의 이름을 가진 문자열의 목록입니다. 이러한 기능은 와일드 카드 가져 오기에 사용할 수 있습니다. 모듈과 마찬가지로 패키지에서 와일드 카드를 가져올 때 __all__
사용자 정의합니다 *
. [ @MartinStettner ]
다음은 Python MySQL 커넥터 에서 발췌 한 내용입니다 __init__.py
.
__all__ = [
'MySQLConnection', 'Connect', 'custom_error_exception',
# Some useful constants
'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
'HAVE_CEXT',
# Error handling
'Error', 'Warning',
...etc...
]
패키지의 경우 별표가없는 별표 인__all__
기본 경우 는 복잡합니다. 파일 시스템을 사용하여 패키지의 모든 모듈을 검색하려면 파일 시스템을 사용하는 것이 비용이 많이 들기 때문입니다. 대신 문서를 읽을 때 정의 된 객체 만 __init__.py
가져 옵니다 .
경우
__all__
정의되지 않은, 문은from sound.effects import *
않습니다 하지 패키지의 모든 서브 모듈 가져sound.effects
현재 네임 스페이스로를; 패키지sound.effects
를 가져 왔는지 확인하고 (초기화 코드를 실행 중일 수 있음__init__.py
) 패키지에 정의 된 이름을 가져옵니다. 여기에는에 의해 정의 된 (및 명시 적으로로드 된 하위 모듈) 이름이 포함됩니다__init__.py
. 또한 이전 import 문으로 명시 적으로로드 된 패키지의 하위 모듈도 포함합니다.
와일드 카드 가져 오기는 독자와 많은 자동화 도구를 혼동하기 때문에 피해야합니다.
[ PEP 8 , @ToolmakerSteve]
from <package> import *
하지 않고 __all__
에서 __init__.py
되는 모듈 중 하나를 가져올 수 없습니다 .
__init__.py
작동한다고 말하고 싶었습니다 . 그러나 그것이 정확하거나 특히 밑줄이 붙은 개체가 제외되는지 확실하지 않습니다. 또한 모듈 및 패키지 섹션을 더 명확하게 분리했습니다. 당신의 생각?
에서 (비공식) 파이썬 레퍼런스 위키 :
모듈이 정의한 공개 이름은 모듈의 네임 스페이스를 변수 이름으로 확인하여 결정됩니다
__all__
. 정의 된 경우 해당 모듈에서 정의하거나 가져온 이름 인 일련의 문자열이어야합니다. 이름__all__
은 모두 공개로 간주되며 존재해야합니다.__all__
이 정의되지 않은 경우 공개 이름 세트에는 밑줄 문자 ( "_")로 시작하지 않는 모듈 네임 스페이스에있는 모든 이름이 포함됩니다.__all__
전체 공개 API를 포함해야합니다. API에 포함되지 않은 항목 (예 : 모듈 내에서 가져 와서 사용 된 라이브러리 모듈)을 실수로 내 보내지 않도록합니다.
__all__
파이썬 모듈의 공개 API를 문서화하는 데 사용됩니다. 선택 사항이지만 __all__
사용해야합니다.
다음은 Python 언어 참조 에서 발췌 한 내용입니다 .
모듈이 정의한 공개 이름은 모듈의 네임 스페이스를 변수 이름으로 확인하여 결정됩니다
__all__
. 정의 된 경우 해당 모듈에서 정의하거나 가져온 이름 인 일련의 문자열이어야합니다. 이름__all__
은 모두 공개로 간주되며 존재해야합니다.__all__
이 정의되지 않은 경우 공개 이름 세트에는 밑줄 문자 ( '_')로 시작하지 않는 모듈 네임 스페이스에있는 모든 이름이 포함됩니다.__all__
전체 공개 API를 포함해야합니다. API에 포함되지 않은 항목 (예 : 모듈 내에서 가져 와서 사용 된 라이브러리 모듈)을 실수로 내 보내지 않도록합니다.
PEP 8 은 유사한 단어를 사용하지만 가져온 이름이 없을 때 가져온 이름이 공개 API의 일부가 아님을 분명히합니다 __all__
.
내부 검사를보다 잘 지원하려면 모듈이
__all__
속성을 사용하여 공개 API에서 이름을 명시 적으로 선언해야 합니다.__all__
빈 목록으로 설정 하면 모듈에 공개 API가 없음을 나타냅니다.[...]
가져온 이름은 항상 구현 세부 사항으로 간주되어야합니다. 다른 모듈은 포함 된 모듈의 API (예 : 하위 모듈의 기능을 노출
os.path
하는 패키지__init__
모듈) 와 같이 명시 적으로 문서화 된 부분이 아닌 한 가져온 이름에 간접적으로 액세스 할 수 없습니다 .
또한 다른 답변에서 지적했듯이 패키지의 와일드 카드 가져 오기__all__
를 활성화하는 데 사용 됩니다 .
import 문은 다음 규칙을 사용합니다. 패키지의
__init__.py
코드가이라는 목록을 정의하면 발견__all__
될 때 가져와야하는 모듈 이름 목록으로 간주from package import *
됩니다.
__all__
from <module> import *
진술에 영향을 미칩니다 .
이 예제를 고려하십시오.
foo
├── bar.py
└── __init__.py
에서 foo/__init__.py
:
우리는 정의하지 않으면 (암시) __all__
, 다음 from foo import *
단지에 정의 된 이름을 가져옵니다 foo/__init__.py
.
우리가 정의하는 경우 (명시) __all__ = []
, 다음 from foo import *
아무것도 가져올 수 없습니다.
우리가 정의하는 경우 (명시) __all__ = [ <name1>, ... ]
, 다음 from foo import *
만 이름을 가져옵니다.
암시 적 인 경우 파이썬은로 시작하는 이름을 가져 오지 않습니다 _
. 그러나을 사용하여 이러한 이름을 강제로 가져올 수 있습니다 __all__
.
여기 에서 Python 문서를 볼 수 있습니다 .
__all__
from foo import *
작동 방식에 영향을줍니다 .
함수 나 클래스의 본문이 아닌 모듈 본문 안에있는 코드 *
는 from
명령문 에서 별표 ( )를 사용할 수 있습니다 .
from foo import *
*
모든 모듈의 속성 것을 요청 foo
(밑줄 그 시작 제외)은 수입 모듈의 전역 변수로 구속. 때 foo
속성을 가지고 __all__
, 속성의 값은이 유형에 구속 된 이름의 목록입니다 from
문.
경우 foo
A는 패키지 와 __init__.py
정의라는 이름의 목록 __all__
, 때 가져와야 서브 모듈 이름의리스트를 보낸다 from foo import *
발생합니다. 경우 __all__
정의되지 않은, 문 from foo import *
어떤 이름 수입은 패키지에 정의되어있다. 여기에는에 의해 정의 된 (및 명시 적으로로드 된 하위 모듈) 이름이 포함됩니다 __init__.py
.
참고 __all__
이없는이 목록이 될 수 있습니다. import
명령문 의 문서에 따라 정의 된 경우 모듈에서 정의하거나 가져온 이름 의 문자열 시퀀스__all__
여야합니다 . 따라서 튜플을 사용하여 메모리와 CPU주기 를 절약 할 수도 있습니다 . 모듈이 단일 공개 이름을 정의하는 경우 쉼표를 잊지 마십시오.
__all__ = ('some_name',)
"import *"가 왜 나쁜가요?를 참조하십시오 .
이것은 PEP8에 정의되어 있습니다 :
전역 변수 이름
(이러한 변수가 하나의 모듈 내에서만 사용되기를 바랍니다.) 규칙은 함수의 규칙과 거의 같습니다.
via를 사용하도록 설계된 모듈은 전역 내보내기를 방지
from M import *
하는__all__
메커니즘을 사용하거나 이러한 전역에 밑줄을 붙이는 기존 규칙을 사용해야합니다 (이러한 전역이 "모듈 비공개"임을 나타내려고 할 수 있습니다).
PEP8은 기본 Python 배포판에 표준 라이브러리를 포함하는 Python 코드에 대한 코딩 규칙을 제공합니다. 이것을 더 많이 따를수록 원래 의도에 더 가깝습니다.
__all__
경우 언급되지 않은 객체는__all__
정확하게 숨겨지지 않습니다. 당신이 그들의 이름을 알고 있다면 그것들을보고 정상적으로 정상적으로 접근 할 수 있습니다. 어쨌든 권장하지 않는 "import *"의 경우에만 구별에 가중치가 있습니다.