如何在模块中定义与 __all__ 分开的 `from ... import *` API?
我有一个模块,这个模块大致分为两部分:一部分是一些工具函数,另一部分是核心的API函数。我需要把所有这些函数都放在__all__
里,这样才能让help()
这个功能好用,同时也能明确哪些函数、类等是可以被外部使用的。不过,我也想支持from mymodule import *
这种方式,这样可以只把核心功能导入到其他模块中。请问有没有办法做到这一点呢?
4 个回答
我觉得没有办法做到这一点,至少没有什么好的方法。就连Python官方的模块里也有很多实用的函数出现在文档中。如果你觉得分开很重要,我建议你创建两个不同的模块。总之,使用 from module import *
这种写法并不是个好习惯,我不推荐你这么做,更不建议你为了这种写法来设计你的模块 :)
Ethan,你的 fake_module
其实用普通的Python就能更好地实现。只需要把你的代码放到一个目录结构里:
mymodule
__init__.py
api.py
util.py
_mymodule.py
其中 _mymodule.py
里放的是你现在的代码。
在你的 __init__.py
文件里:
from _mymodule import *
在你的 api.py
文件里:
# explicity import only those api classes you want to expose
# this will allow you to call `from mymodule.api import *`
import from _mymodule ApiClass1
import from _mymodule ApiClass2
# etc
对你的 util.py
文件也这样做:
# explicity import only those util classes you want to expose
# this will allow you to call `from mymodule.util import *`
import from _mymodule UtilClass1
import from _mymodule UtilClass2
# etc
这样你就可以:
# import everything willy nilly for your help()
from mymodule import *
# or import only the "public" values from api and util
from mymodule.api import *
from mymodule.util import *
把代码分开这样做,可以帮助你更好地组织一个比较大的模块,同时又能从顶层命名空间访问它。不过我同意 brandizzi
的看法,在使用这个模块的代码里用 from mymodule import *
通常不是个好主意。你在导入时的方便,可能会让使用这些导入的代码变得不那么清晰。
差不多。不过,虽然你不能让 __all__
同时起到两个作用,但你可以添加一个自己的虚拟 API 模块,这样就可以导入它了...
class fake_module(object):
def __init__(self, name, *args):
self.name = name
self.__all__ = []
all_objects = globals()
for name in args:
self.__dict__[name] = all_objects[name]
self.__all__.append(name)
def register(self):
sys.modules["%s.%s" % (__name__, self.name)] = self
fake_module('api', 'class1', 'class2', 'func3', 'exception4').register()
然后在其他模块中,不用写 from mymodule import *
,而是可以写 from mymodule.api import *
,这样就能只获取你想要的部分,同时还可以把所有东西放在一个模块里。
注意: from ... import *
通常不是一个好的做法,使用时要非常小心,并且只在那些明确说明可以这样使用的模块或包中使用。