from Bar_implementation import *
from Baz_implementation import *
__all__ = ['Bar', 'Baz']
如果您尚未准备好在顶级API中发布 Baz ,则可以在您的顶级 __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
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()
无论是作为main运行还是由另一个函数导入,这都可以正常工作 .
$ cat > run.py
import main
main.main()
$ python run.py
main
使用 import * 的API配置也可以使用:
$ 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
356
它还改变了pydoc将显示的内容:
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'
>>> 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
9 回答
它是该模块的公共对象列表,由
import *
解释 . 它会覆盖隐藏以下划线开头的所有内容的默认设置 .链接到,但未在此明确提及,正是在使用
__all__
时 . 它是一个字符串列表,用于定义在模块上使用from <module> import *
时模块中将导出哪些符号 .例如,
foo.py
中的以下代码显式导出符号bar
和baz
:然后可以像这样导入这些符号:
如果上面的
__all__
被注释掉,则此代码将执行完成,因为import *
的默认行为是从给定的命名空间导入所有不以下划线开头的符号 .参考:https://docs.python.org/3.5/tutorial/modules.html#importing-from-a-package
NOTE:
__all__
仅影响from <module> import *
行为 .__all__
中未提及的成员仍可从模块外部访问,并可使用from <module> import <member>
导入 .我只是准确地添加这个:
所有其他答案都涉及模块 . 最初的问题在
__init__.py
文件中明确提到__all__
,所以这是关于python包的 .通常,
__all__
仅在使用import
语句的from xxx import *
变体时才起作用 . 这适用于包和模块 .其他答案中解释了模块的行为 . 包的确切行为详细描述为here .
简而言之,包级别上的
__all__
与模块大致相同,只是它处理包中的模块(与在模块中指定名称相反) . 所以__all__
指定当我们使用from package import *
时应加载并导入当前命名空间的所有模块 .最大的区别是,当您在包的
__init__.py
中省略__all__
的声明时,语句from package import *
将根本不会导入任何内容(文档中说明了异常,请参阅上面的链接) .另一方面,如果在模块中省略
__all__
,则"starred import"将导入模块中定义的所有名称(不以下划线开头) .__all__做什么?
它从模块声明了语义"public"名称 . 如果
__all__
中有名称,则希望用户使用它,并且可以期望它不会更改 .它还会产生程序化影响:
进口*
__all__
在一个模块中,例如module.py
:表示当您从模块中
import *
时,仅导入__all__
中的那些名称:文档工具
文档和代码自动完成工具可能(实际上应该)检查
__all__
以确定模块中可用的名称 .init.py使目录成为Python包
来自docs:
所以
__init__.py
可以为包声明__all__
.管理API:
包通常由可以相互导入的模块组成,但必须与
__init__.py
文件绑定在一起 . 该文件是使目录成为实际Python包的原因 . 例如,假设您有以下内容:在你写的
__init__.py
中:在
module_1
你有:在
module_2
你有:现在你已经提供了一个完整的api,其他人可以在导入你的包时使用,如下所示:
并且它们不会包含您在创建模块时使用的所有其他名称,这些名称会使
package
命名空间变得混乱 .init.py中
all
经过更多的工作,也许你已经决定模块太大而且需要拆分 . 所以你做了以下事情:
在每个
__init__.py
中,您声明__all__
,例如在module_1中:和module_2的
__init__.py
:您可以轻松地向API添加可以在子包级别而不是子包的模块级别管理的内容 . 如果您要为API添加新名称,只需更新
__init__.py
,例如在module_2中:如果您尚未准备好在顶级API中发布
Baz
,则可以在您的顶级__init__.py
中:如果您的用户知道
Baz
的可用性,他们可以使用它:但如果他们不知道它,其他工具(如pydoc)不会通知他们 .
您可以稍后在
Baz
准备好黄金时间时更改它:前缀_与__all__:
默认情况下,Python将导出所有不以
_
开头的名称 . 你当然可以依靠这种机制 . 事实上,Python标准库中的某些包确实依赖于此,但为了这样做,它们为其导入设置了别名,例如,在_829280中:使用
_
约定可以更加优雅,因为它消除了再次命名名称的冗余 . 但是它增加了导入的冗余(如果你有很多它们)并且很容易忘记这样做 - 并且你想要的最后一件事就是必须无限期地支持你想要的只是一个实现细节,只是因为在命名函数时忘了给_
添加前缀 .我个人在模块的开发生命周期的早期写了一个
__all__
,以便其他可能使用我的代码的人知道他们应该使用什么而不是使用 .标准库中的大多数包也使用
__all__
.避免__all__有意义
在以下情况下,坚持
_
前缀约定代替__all__
是有意义的:您仍处于早期开发模式且没有用户,并且不断调整您的API .
也许您确实拥有用户,但您拥有覆盖API的单元测试,并且您仍在积极地添加API并在开发中进行调整 .
导出装饰器
使用
__all__
的缺点是您必须编写两次导出的函数和类的名称 - 并且信息与定义分开 . 我们可以使用装饰器来解决这个问题 .我从David Beazley _829289的传统进口商那里得到了这样一个出口装饰的想法 . 如果你有一个特殊的导入钩子或系统,我不保证,但如果你采用它,退出是相当简单的 - 你只需要手动将名称添加回
__all__
因此,在例如实用程序库中,您将定义装饰器:
然后,在那里定义一个
__all__
,你这样做:无论是作为main运行还是由另一个函数导入,这都可以正常工作 .
使用
import *
的API配置也可以使用:它还改变了pydoc将显示的内容:
module1.py
module2.py
$ pydoc module1
$ pydoc module2
我在所有模块中声明
__all__
,以及强调内部细节,这些在使用您以前从未在现场解释器会话中使用过的东西时非常有用 .来自(An Unofficial) Python Reference Wiki:
__all__自定义<module> import *中的星号
__all__自定义<package> import *中的星号
module是要导入的
.py
文件 .package是具有
__init__.py
文件的目录 . 包通常包含模块 .__all__
让人类知道 module 的"public"特征 . [@ AaronHall]此外,pydoc识别它们 . [@ Longpoke]来自模块导入*
了解如何将
swiss
和cheddar
带入本地命名空间,但不是gouda
:没有
__all__
,任何符号(不以下划线开头)都可用 .没有*的进口不受__all__的影响
导入模块
来自模块导入名称
导入模块为localname
在 package
__all__
的__init__.py
文件中是一个包含公共模块或其他对象名称的字符串列表 . 这些功能可用于通配符导入 . 与模块一样,__all__
在从包中进行通配符导入时自定义*
. [@ MartinStettner]以下是Python MySQL Connector
__init__.py
的摘录:[PEP 8,@ ToolmakerSteve]
__all__
用于记录Python模块的公共API . 虽然它是可选的,但应使用__all__
.以下是the Python language reference的相关摘录:
PEP 8使用了类似的措辞,但是当
__all__
不存在时,它也清楚地表明导入的名称不是公共API的一部分:此外,正如其他答案所指出的,
__all__
用于启用wildcard importing for packages:简答
__all__
影响from <module> import *
语句 .答案很长
考虑这个例子:
在
foo/__init__.py
:(隐式)如果我们没有定义
__all__
,那么from foo import *
将只导入foo/__init__.py
中定义的名称 .(明确)如果我们定义
__all__ = []
,则from foo import *
将不会导入任何内容 .(明确)如果我们定义
__all__ = [ <name1>, ... ]
,则from foo import *
将仅导入这些名称 .请注意,在隐式的情况下,python不会导入以
_
开头的名称 . 但是,您可以使用__all__
强制导入此类名称 .您可以查看Python文档here .