问题:有人可以用Python解释__all__吗?

我越来越多地使用Python,并且不断看到__all__在不同__init__.py文件中设置的变量。有人可以解释这是什么吗?

I have been using Python more and more, and I keep seeing the variable __all__ set in different __init__.py files. Can someone explain what this does?


回答 0

这是该模块的公共对象的列表,由解释import *。它覆盖了隐藏所有以下划线开头的所有内容的默认设置。

It’s a list of public objects of that module, as interpreted by import *. It overrides the default of hiding everything that begins with an underscore.


回答 1

链接到(但未在此处明确提及的)确切是何时__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>

Linked to, but not explicitly mentioned here, is exactly when __all__ is used. It is a list of strings defining what symbols in a module will be exported when from <module> import * is used on the module.

For example, the following code in a foo.py explicitly exports the symbols bar and baz:

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

These symbols can then be imported like so:

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

If the __all__ above is commented out, this code will then execute to completion, as the default behaviour of import * is to import all symbols that do not begin with an underscore, from the given namespace.

Reference: https://docs.python.org/tutorial/modules.html#importing-from-a-package

NOTE: __all__ affects the from <module> import * behavior only. Members that are not mentioned in __all__ are still accessible from outside the module and can be imported with from <module> import <member>.


回答 2

用Python解释__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__一个

管理API:

程序包通常由可以相互导入但必须与__init__.py文件捆绑在一起的模块组成。该文件使目录成为实际的Python包。例如,假设您的软件包中包含以下文件:

package
├── __init__.py
├── module_1.py
└── module_2.py

让我们使用Python创建这些文件,以便您可以继续进行操作-您可以将以下内容粘贴到Python 3 Shell中:

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为声明__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将导出所有不以开头的名称_。您当然可以依靠这种机制。实际上,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

Explain __all__ in Python?

I keep seeing the variable __all__ set in different __init__.py files.

What does this do?

What does __all__ do?

It declares the semantically “public” names from a module. If there is a name in __all__, users are expected to use it, and they can have the expectation that it will not change.

It also will have programmatic affects:

import *

__all__ in a module, e.g. module.py:

__all__ = ['foo', 'Bar']

means that when you import * from the module, only those names in the __all__ are imported:

from module import *               # imports foo and Bar

Documentation tools

Documentation and code autocompletion tools may (in fact, should) also inspect the __all__ to determine what names to show as available from a module.

__init__.py makes a directory a Python package

From the docs:

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path.

In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable.

So the __init__.py can declare the __all__ for a package.

Managing an API:

A package is typically made up of modules that may import one another, but that are necessarily tied together with an __init__.py file. That file is what makes the directory an actual Python package. For example, say you have the following files in a package:

package
├── __init__.py
├── module_1.py
└── module_2.py

Let’s create these files with Python so you can follow along – you could paste the following into a Python 3 shell:

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
""")

And now you have presented a complete api that someone else can use when they import your package, like so:

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

And the package won’t have all the other implementation details you used when creating your modules cluttering up the package namespace.

__all__ in __init__.py

After more work, maybe you’ve decided that the modules are too big (like many thousands of lines?) and need to be split up. So you do the following:

package
├── __init__.py
├── module_1
│   ├── foo_implementation.py
│   └── __init__.py
└── module_2
    ├── Bar_implementation.py
    └── __init__.py

First make the subpackage directories with the same names as the modules:

subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()

Move the implementations:

package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')

create __init__.pys for the subpackages that declare the __all__ for each:

(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")

And now you still have the api provisioned at the package level:

>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>

And you can easily add things to your API that you can manage at the subpackage level instead of the subpackage’s module level. If you want to add a new name to the API, you simply update the __init__.py, e.g. in module_2:

from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']

And if you’re not ready to publish Baz in the top level API, in your top level __init__.py you could have:

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

and if your users are aware of the availability of Baz, they can use it:

import package
package.Baz()

but if they don’t know about it, other tools (like pydoc) won’t inform them.

You can later change that when Baz is ready for prime time:

from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

Prefixing _ versus __all__:

By default, Python will export all names that do not start with an _. You certainly could rely on this mechanism. Some packages in the Python standard library, in fact, do rely on this, but to do so, they alias their imports, for example, in ctypes/__init__.py:

import os as _os, sys as _sys

Using the _ convention can be more elegant because it removes the redundancy of naming the names again. But it adds the redundancy for imports (if you have a lot of them) and it is easy to forget to do this consistently – and the last thing you want is to have to indefinitely support something you intended to only be an implementation detail, just because you forgot to prefix an _ when naming a function.

I personally write an __all__ early in my development lifecycle for modules so that others who might use my code know what they should use and not use.

Most packages in the standard library also use __all__.

When avoiding __all__ makes sense

It makes sense to stick to the _ prefix convention in lieu of __all__ when:

  • You’re still in early development mode and have no users, and are constantly tweaking your API.
  • Maybe you do have users, but you have unittests that cover the API, and you’re still actively adding to the API and tweaking in development.

An export decorator

The downside of using __all__ is that you have to write the names of functions and classes being exported twice – and the information is kept separate from the definitions. We could use a decorator to solve this problem.

I got the idea for such an export decorator from David Beazley’s talk on packaging. This implementation seems to work well in CPython’s traditional importer. If you have a special import hook or system, I do not guarantee it, but if you adopt it, it is fairly trivial to back out – you’ll just need to manually add the names back into the __all__

So in, for example, a utility library, you would define the decorator:

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

and then, where you would define an __all__, you do this:

$ 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()

And this works fine whether run as main or imported by another function.

$ cat > run.py
import main
main.main()

$ python run.py
main

And API provisioning with import * will work too:

$ 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

回答 3

我只是添加这是为了精确:

所有其他答案均涉及模块__all____init__.py文件中明确提到了原始问题,所以这是关于python

通常,__all__仅在使用语句的from xxx import *变体时才起作用import。这适用于软件包以及模块。

模块的行为在其他答案中进行了说明。包的确切行为在此处详细描述。

简而言之,__all__在程序包级别,它与模块大致相同,只是它处理程序包中的模块 (与在模块中指定名称相反)。因此__all__指定当我们使用时应加载并导入到当前命名空间中的所有模块from package import *

最大的区别是,当你忽略的声明__all__在包的__init__.py,该声明from package import *将完全不进口任何东西(有exceptions的文档中解释,见上面的链接)。

另一方面,如果__all__在模块中省略,则“加星号的导入”将导入模块中定义的所有名称(不是以下划线开头)。

I’m just adding this to be precise:

All other answers refer to modules. The original question explicitely mentioned __all__ in __init__.py files, so this is about python packages.

Generally, __all__ only comes into play when the from xxx import * variant of the import statement is used. This applies to packages as well as to modules.

The behaviour for modules is explained in the other answers. The exact behaviour for packages is described here in detail.

In short, __all__ on package level does approximately the same thing as for modules, except it deals with modules within the package (in contrast to specifying names within the module). So __all__ specifies all modules that shall be loaded and imported into the current namespace when us use from package import *.

The big difference is, that when you omit the declaration of __all__ in a package’s __init__.py, the statement from package import * will not import anything at all (with exceptions explained in the documentation, see link above).

On the other hand, if you omit __all__ in a module, the “starred import” will import all names (not starting with an underscore) defined in the module.


回答 4

它还更改了pydoc将显示的内容:

module1.py

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

module2.py

__all__ = ['a', 'b']

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

$ pydoc module1

关于模块module1的帮助:

名称
    模块1

文件
    module1.py

数据 a ='
     A'b ='
     B'c ='C'

$ pydoc module2

关于模块module2的帮助:

名称
    模块2

文件
    module2.py

数据 __all__ = ['a','b']
     a ='
     A'b ='B'

__all__在所有模块中都声明了内容,并强调了内部细节,这些内容在使用实时解释器会话中从未使用过的功能时确实有用。

It also changes what pydoc will show:

module1.py

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

module2.py

__all__ = ['a', 'b']

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

$ pydoc module1

Help on module module1:

NAME
    module1

FILE
    module1.py

DATA a = 'A'
    b = 'B'
    c = 'C'

$ pydoc module2

Help on module module2:

NAME
    module2

FILE
    module2.py

DATA __all__ = ['a', 'b']
    a = 'A'
    b = 'B'

I declare __all__ in all my modules, as well as underscore internal details, these really help when using things you’ve never used before in live interpreter sessions.


回答 5

__all__定制*from <module> import *

__all__定制*from <package> import *


一个模块.py意味着要导入的文件。

是一个目录__init__.py文件。软件包通常包含模块。


模组

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

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__让人们知道模块的“公共”功能。[ @AaronHall ] 另外,pydoc可以识别它们。[ @Longpoke ]

模块导入*

了解如何swisscheddar被带入当地的命名空间,而不是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文件中是带有公共模块或其他对象名称的字符串列表。这些功能可用于通配符导入。与模块一样,自定义从软件包导入通配符的时间。[ @MartinStettner ] __all____all__*

这是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...

    ]

缺省情况下,对于软件包情况很复杂,因为明显的行为是很昂贵的:使用文件系统搜索软件包中的所有模块。相反,在我阅读文档时,仅__init__.py导入中定义的对象:

如果__all__没有定义,语句from sound.effects import *不会导入从包中的所有子模块sound.effects到当前的命名空间; 它仅确保sound.effects已导入包(可能在中运行任何初始化代码__init__.py),然后导入包中定义的任何名称。这包括由定义的任何名称(以及明确加载的子模块)__init__.py。它还包括以前的import语句显式加载的包的所有子模块。


应避免使用通配符导入,因为它们会使读者和许多自动化工具感到困惑。

[ PEP 8,@ ToolmakerSteve]

__all__ customizes * in from <module> import *

__all__ customizes * 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, , 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]


回答 6

摘自(非官方)Python参考维基

模块定义的公共名称是通过检查模块的命名空间中名为的变量来确定的__all__;如果已定义,则它必须是由该模块定义或导入的名称的字符串序列。给出的名称__all__均被视为公开名称,必须存在。如果__all__未定义,则公共名称集将包含在模块命名空间中找到的所有名称,这些名称不以下划线字符(“ _”)开头。__all__应该包含整个公共API。目的是避免意外导出不属于API的项目(例如在模块中导入和使用的库模块)。

From (An Unofficial) Python Reference Wiki:

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


回答 7

__all__用于记录Python模块的公共API。尽管它是可选的,但__all__应使用。

这是Python语言参考中的相关摘录:

模块定义的公共名称是通过检查模块的命名空间中名为的变量来确定的__all__;如果已定义,则它必须是由该模块定义或导入的名称的字符串序列。给出的名称__all__均被视为公开名称,必须存在。如果__all__未定义,则公共名称集将包含在模块命名空间中找到的所有名称,这些名称不以下划线字符(_)开头。__all__应该包含整个公共API。目的是避免意外导出不属于API的项目(例如在模块中导入和使用的库模块)。

PEP 8使用类似的措辞,尽管它也清楚地表明,如果__all__缺少导入的名称,则它们不属于公共API :

为了更好地支持自省,模块应使用__all__属性在其公共API中显式声明名称。设置__all__为空列表表示该模块没有公共API。

[…]

导入的名称应始终被视为实现细节。其他模块不得依赖对此类导入名称的间接访问,除非它们是包含模块的API中明确记录的一部分,例如os.path__init__暴露了子模块功能的软件包模块。

此外,如其他答案所指出的,__all__用于启用软件包的通配符导入

import语句使用以下约定:如果程序包的__init__.py代码定义了名为的列表__all__,则将其视为from package import *遇到时应导入的模块名称的列表。

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


回答 8

简短答案

__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 *则将仅导入这些名称。

请注意,在隐式情况下,python不会导入以开头的名称_。但是,您可以使用以下命令强制导入此类名称__all__

您可以在此处查看Python文档。

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.


回答 9

__all__影响from foo import *工作方式。

在模块主体内(但不在函数或类主体内)的代码可以*from语句中使用星号():

from foo import *

*所有属性模块的要求foo(除了那些下划线开头)绑定为导入模块中的全局变量。当foo具有属性时__all__,属性的值是受此类型的绑定的名称的列表from语句。

If foo是一个,它__init__.py定义了一个名为__all__,则将其视为from foo import *遇到时应导入的子模块名称的列表。如果__all__未定义,则该语句将from foo import *导入包中定义的任何名称。这包括由定义的任何名称(以及明确加载的子模块)__init__.py

请注意,__all__不必一定是列表。根据import声明中的文档,如果已定义,则__all__必须是字符串序列是模块定义或导入的名称。因此,您也可以使用元组来节省一些内存和CPU周期。只是不要忘记逗号,以防模块定义了单个公共名称:

__all__ = ('some_name',)

另请参阅“ import *”为什么不好?

__all__ affects how from foo import * works.

Code that is inside a module body (but 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 (except those beginning with underscores) 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.

If foo is a package and its __init__.py defines a list named __all__, it is taken to be the list of submodule names that should be imported when from foo import * is encountered. If __all__ is not defined, the statement from foo import * imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py.

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?


回答 10

这在PEP8定义在这里

全局变量名

(我们希望这些变量只能在一个模块内使用。)约定与函数的约定大致相同。

设计用于via的模块from M import *应使用__all__防止导出全局变量的机制,或使用在下划线之前为此类全局变量加上前缀的较早的约定(您可能需要这样做以指示这些全局变量是“模块非公共的”)。

PEP8为包含主要Python发行版中的标准库的Python代码提供了编码约定。您遵循的越多,您就越接近原始意图。

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.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。