当前,我们有一个类似以下内容的Python库:
Jupiter/
__init__.py
Ganymede.py
Callisto.py
Ganymede.py
依次包含函数Foo()
,Bar()
等。我们现有的脚本通过
from Jupiter import Ganymede
# later in the program...
Ganymede.Foo()
我想重新组织一下,使目录看起来更像
Jupiter/
__init__.py
Ganymede/
__init__.py
functions.py
Callisto/
__init__.py
functions.py
无需破坏或修改任何使用Jupiter的现有脚本。
如果Ganymede/__init__.py
使用"The import system" documentation中所述的导入语法:
from .functions import *
然后,Foo()
和Bar()
最终出现在Ganymede的命名空间中,但是Ganymede的help()
没有提及它们。
>>> from Jupiter import Ganymede
>>> dir(Ganymede)
['Bar', 'Foo', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'functions']
>>> help(Ganymede)
Help on package Jupiter.Ganymede in Jupiter:
NAME
Jupiter.Ganymede
PACKAGE CONTENTS
functions
FILE
x:\yadda\yadda\ganymede\__init__.py
我真的很希望help(Ganymede)
自动列出所有可用的函数和类。
我想我可以execfile("functions.py")
中的Ganymede/__init__.py
,但是我觉得必须有一些更清洁的方法来做到这一点。还是没有?
我需要在Python 2.7.15和3.5.3中都可以使用的东西。
答案 0 :(得分:1)
在__all__
中创建一个__init__.py
。
如果__all__
中已经有functions.py
,则可以将其导入:
from .functions import *
from .functions import __all__
如果要将多个模块合并在一起,则必须更加冗长
from .functions import *
from .classes import *
from . import functions
from . import classes
__all__ = functions.__all__ + classes.__all__
或者,当然,您始终可以保持明确:
from .functions import *
__all__ = ['spam', 'eggs']
或者,如果您想动态构建它:
from .functions import *
from . import functions
__all__ = [name for name in dir(functions) if not name.startswith('_')]
…或(相当hacky,但如果您有一个__init__.py
可以从许多子模块中收集名称并且不执行其他操作,则有时会很有用)…
from .functions import *
__all__ = [name for name in globals() if not name.startswith('_')]
…或者您可以变得非常聪明,并以某种方式进行操作,例如multiprocessing
可以做到: 1
from . import functions
__all__ = [name for name in functions if not name.startswith('_')]
globals().update({name: getattr(functions, name) for name in __all__})
请记住,__all__
也将影响某人执行from Ganymede import *
(实际上是that's the main purpose of __all__
)时发生的情况,以及inspect
和其他工具报告为您包裹的公开成员。
我不确定在没有help
的情况下__all__
的行为是否在任何地方都有记录(交互式help
的作品通常只被轻易记录了……),而且还不是与import
认为公开的内容相同。
1。好吧,multiprocessing
实际上更聪明/更聪明;它将属性不是从子模块中移出,而是从该子模块的动态单例属性中移出,该属性在主进程和子进程上进行了不同的设置,并相应地更改了程序包的某些顶级功能……