Program Tip

누군가 파이썬에서 __all__을 설명 할 수 있습니까?

programtip 2020. 9. 28. 09:55
반응형

누군가 파이썬에서 __all__을 설명 할 수 있습니까?


저는 Python을 점점 더 많이 사용하고 __all__있으며 다른 __init__.py파일에 설정된 변수를 계속 볼 수 있습니다. 누군가 이것이 무엇을 설명 할 수 있습니까?


에 의해 해석되는 해당 모듈의 공용 객체 목록입니다 import *. 밑줄로 시작하는 모든 항목을 숨기는 기본값을 재정의합니다.


여기에 명시 적으로 언급되지는 않았지만에 링크되어있는 것은 정확히 언제 __all__사용 되는지 입니다. 모듈에서를 사용할 때 내보낼 모듈의 심볼을 정의하는 문자열 목록입니다 from <module> import *.

예를 들어의 다음 코드는 foo.py기호를 명시 적으로 내 보냅니다 .barbaz

__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>.


나는 이것을 정확하게 추가하고 있습니다.

다른 모든 답변은 모듈을 참조 합니다 . 파일에 명시 적으로 언급 __all__원래 질문 __init__.py은 python packages 에 관한 것 입니다.

일반적으로 문장 __all__from xxx import *변형 import이 사용될 때만 작동합니다 . 이는 패키지뿐만 아니라 모듈에도 적용됩니다.

모듈의 동작은 다른 답변에 설명되어 있습니다. 패키지의 정확한 동작은 여기 에 자세히 설명되어 있습니다 .

간단히 말해서, __all__패키지 수준에서 모듈의 경우와 거의 동일한 작업을 수행합니다. 단 , 패키지 내에서 모듈 을 처리한다는 점만 다릅니다 ( 모듈 내에서 이름 을 지정하는 것과는 대조적으로 ). 그래서 __all__우리가 사용할 때로드되고 현재 네임 스페이스로 가져올 모든 모듈을 지정합니다 from package import *.

큰 차이점은 패키지의 선언 생략 하면 명령문 이 아무것도 가져 오지 않는다는 것입니다 (문서에 설명 된 예외 사항이있는 경우 위 링크 참조).__all____init__.pyfrom package import *

반면에 __all__모듈에서 생략 하면 "별표 표시된 가져 오기"는 모듈에 정의 된 모든 이름 (밑줄로 시작하지 않음)을 가져옵니다.


파이썬에서 __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 디렉토리를 Python 패키지로 만듭니다.

로부터 문서 :

__init__.py파일은 Python이 디렉토리를 패키지를 포함하는 것으로 취급하도록하는 데 필요합니다. 이는 문자열과 같은 공통 이름을 가진 디렉토리가 나중에 모듈 검색 경로에서 발생하는 유효한 모듈을 의도하지 않게 숨기는 것을 방지하기 위해 수행됩니다.

가장 간단한 경우 __init__.py에는 빈 파일 일 수도 있지만 패키지에 대한 초기화 코드를 실행하거나 __all__변수를 설정할 수도 있습니다.

그래서이 __init__.py을 선언 할 수 있습니다 __all__A의 패키지 .

API 관리 :

패키지는 일반적으로 서로 가져올 수있는 모듈로 구성되지만 반드시 __init__.py파일 과 함께 연결되어야 합니다. 이 파일은 디렉토리를 실제 Python 패키지로 만드는 것입니다. 예를 들어 다음이 있다고 가정합니다.

 package/
   |-__init__.py # makes directory a Python package
   |-module_1.py
   |-module_2.py

__init__.py당신은 쓰기 :

from module_1 import *
from module_2 import *

그리고 module_1당신은 :

__all__ = ['foo',]

그리고 module_2당신은 :

__all__ = ['Bar',]

이제 다른 사람이 패키지를 가져올 때 사용할 수있는 완전한 API를 다음과 같이 제시했습니다.

import package
package.foo()
package.Bar()

그리고 package네임 스페이스를 복잡하게 만드는 모듈을 만들 때 사용한 다른 모든 이름을 가지지 않습니다 .

__all____init__.py

더 많은 작업을 마친 후 모듈이 너무 커서 분할해야한다고 결정했을 수 있습니다. 따라서 다음을 수행합니다.

 package/
   |-__init__.py
   |-module_1/
   |  |-__init__.py
   |  |-foo_implementation.py
   |-module_2/
      |-__init__.py
      |-Bar_implementation.py

그리고 각각 에서 예를 들어 module_1에서 __init__.py선언합니다 __all__.

from foo_implementation import *
__all__ = ['foo']

그리고 module_2의 __init__.py:

from Bar_implementation import *
__all__ = ['Bar']

또한 하위 패키지의 모듈 수준 대신 하위 패키지 수준에서 관리 할 수있는 항목을 API에 쉽게 추가 할 수 있습니다. API에 새 이름을 추가하려면 __init__.pymodule_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__경우 대신 접두사 규칙 을 고수하는 것이 좋습니다 .

  • 아직 초기 개발 모드이고 사용자가 없으며 지속적으로 API를 조정하고 있습니다.
  • 사용자가있을 수 있지만 API를 다루는 단위 테스트가 있고 여전히 API에 적극적으로 추가하고 개발 중입니다.

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

또한 pydoc이 표시 할 내용을 변경합니다.

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc 모듈 1

module1 모듈에 대한 도움말 :

이름
    module1

파일
    module1.py

DATA
     = 'A'
     , B = 'B'
     C = 'C'

$ pydoc 모듈 2

module2 모듈에 대한 도움말 :

이름
    모듈 2

파일
    module2.py

DATA 
    __all__ = 'A', 'B']
     = 'A'
     , B = 'B'

저는 __all__모든 모듈에서 내부 세부 사항을 강조 할뿐만 아니라 라이브 통역 세션에서 이전에 사용하지 않은 것을 사용할 때 정말 도움이됩니다.


에서 (비공식) 파이썬 레퍼런스 위키 :

The public names defined by a module are determined by checking the module's namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module's namespace which do not begin with an underscore character ("_"). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).


__all__ customizes the asterisk in from <module> import *

__all__ customizes the asterisk in from <package> import *


A module is a .py file meant to be imported.

A package is a directory with a __init__.py file. A package usually contains modules.


MODULES

""" cheese.py - an example module """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__ lets humans know the "public" features of a module.[@AaronHall] Also, pydoc recognizes them.[@Longpoke]

from module import *

See how swiss and cheddar are brought into the local namespace, but not 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

Without __all__, any symbol (that doesn't start with an underscore) would have been available.


Imports without * are not affected by __all__


import module

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

from module import names

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

import module as localname

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

PACKAGES

In the __init__.py file of a package __all__ is a list of strings with the names of public modules or other objects. Those features are available to wildcard imports. As with modules, __all__ customizes the * when wildcard-importing from the package.[@MartinStettner]

Here's an excerpt from the Python MySQL Connector __init__.py:

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

The default case, asterisk with no __all__ for a package, is complicated, because the obvious behavior would be expensive: to use the file system to search for all modules in the package. Instead, in my reading of the docs, only the objects defined in __init__.py are imported:

If __all__ is not defined, the statement from sound.effects import * does not import all submodules from the package sound.effects into the current namespace; it only ensures that the package sound.effects has been imported (possibly running any initialization code in __init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements.


Wildcard imports ... should be avoided as they [confuse] readers and many automated tools.

[PEP 8, @ToolmakerSteve]


Short answer

__all__ affects from <module> import * statements.

Long answer

Consider this example:

foo
├── bar.py
└── __init__.py

In foo/__init__.py:

  • (Implicit) If we don't define __all__, then from foo import * will only import names defined in foo/__init__.py.

  • (Explicit) If we define __all__ = [], then from foo import * will import nothing.

  • (Explicit) If we define __all__ = [ <name1>, ... ], then from foo import * will only import those names.

Note that in the implicit case, python won't import names starting with _. However, you can force importing such names using __all__.

You can view the Python document here.


__all__ is used to document the public API of a Python module. Although it is optional, __all__ should be used.

Here is the relevant excerpt from the Python language reference:

The public names defined by a module are determined by checking the module’s namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ('_'). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).

PEP 8 uses similar wording, although it also makes it clear that imported names are not part of the public API when __all__ is absent:

To better support introspection, modules should explicitly declare the names in their public API using the __all__ attribute. Setting __all__ to an empty list indicates that the module has no public API.

[...]

Imported names should always be considered an implementation detail. Other modules must not rely on indirect access to such imported names unless they are an explicitly documented part of the containing module's API, such as os.path or a package's __init__ module that exposes functionality from submodules.

Furthermore, as pointed out in other answers, __all__ is used to enable wildcard importing for packages:

The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered.


__all__ affects how from ... import * works.

Code that is inside a module body (not in the body of a function or class) may use an asterisk (*) in a from statement:

from foo import *

The * requests that all attributes of module foo be bound as global variables in the importing module. When foo has an attribute __all__, the attribute's value is the list of the names that are bound by this type of from statement. Otherwise, this type of from statement binds all attributes of foo except those beginning with underscores.

Note that __all__ doesn't have to be a list. As per the documentation on the import statement, if defined, __all__ must be a sequence of strings which are names defined or imported by the module. So you may as well use a tuple to save some memory and CPU cycles. Just don't forget a comma in case the module defines a single public name:

__all__ = ('some_name',)

See also Why is “import *” bad?


This is defined in PEP8 here:

Global Variable Names

(Let's hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.

Modules that are designed for use via from M import * should use the __all__ mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are "module non-public").

PEP8 provides coding conventions for the Python code comprising the standard library in the main Python distribution. The more you follow this, closer you are to the original intent.

참고URL : https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python

반응형