我希望my_module
将__all__
导出为空列表,即
from my_module import *
assert '__all__' in dir() and __all__ == []
我可以像这样导出__all__
(在'my_module.py'中):
__all__ = ['__all__']
然而,它可预测地将__all__
绑定到自身,所以
from my_module import *
assert '__all__' in dir() and __all__ == ['__all__']
如何将__all__
导出为空列表?如果做不到这一点,我如何挂钩导入过程,将__all__
放入每个顶级__dict__
语句的导入模块import my_module
中,绕过模块缓存。
答案 0 :(得分:2)
我首先要说的是,在我看来,这是一个可怕的想法。你真的不应该隐含地改变从模块导出的内容,这与Zen of Python相反:显式优于隐式。。
我同意关于你引用的问题的highest-voted answer; Python已经有一种机制来标记函数' private'按照惯例,我们使用前导下划线来表示函数不应被视为模块API的一部分。这种方法适用于现有工具,而装饰器动态设置__all__
,这肯定会破坏静态代码分析器。
那就是,这是一只霰弹枪指着你的脚。小心使用。
您想要的是在导入名称时检测的方法。你通常不能这样做; import
语句没有挂钩。从源导入模块后,module
对象将添加到sys.modules
并重新用于后续导入,但该对象不会通知导入。
您可以做的事情是挂钩属性访问。不使用默认模块对象,但您可以将任何对象填充到sys.modules
中,并将其视为模块。您甚至可以将模块类型子类化,然后为其添加__getattribute__
方法。在使用from module import name
导入任何名称时,系统会调用它,对于使用__all__
的{{1}}中列出的所有名称,以及在Python 3中,{{即使只执行from module import *
,所有导入表单也会访问1}}。
然后你可以通过sys._getframe()
使用它来破解调用框架全局变量:
__spec__
答案 1 :(得分:1)
那个人在第一个装饰器应用程序上设置
__all__
,因此不显式导出任何内容会导致它隐式导出所有内容。我正在努力改进这个设计:如果导入了装饰器,那么无论它的用法如何,都不会导出我的默认值。
只需将__all__
设置为模块开头的空列表,例如:
# this is my_module.py
from utilitymodule import public
__all__ = []
# and now you could use your @public decorator to optionally add module to it