2015-09-06 57 views
1

我定义一个包,包括一组模块的动态增长:如何在包中的__init__.py中的子模块中公开每个名称?

- mypackage 
    - __init__.py 
    - module1.py 
    - module2.py 
    - module3.py 
    ... many more .py files will be added 

我可以每个模块在__init__.py这样暴露每名:

from module1 import * 
from module2 import * 
from module3 import * 

现在,当我import mypackage在客户端代码,我得到所有在子模块中定义的名称:

# suppose funcA is defined in module1, class B is defined in module2 
import mypackage 
mypackage.funcA() # call module1.funcA 
b = mypackage.B() # module2.B 

问题是,我可以定义mypackage中有许多新模块,我不想在每次向包中添加新模块时添加额外的行from modulex import *__init__.py

在所有子模块中动态导出名称的最佳方法是什么?

+0

也许'eval()'在目录内容上? –

+0

既没有列举出你要导入的东西,也没有从中导入的东西,这会让它很难追踪错误并能够读取,仅仅是我的2美分 – KevinOrr

回答

2

我不知道如果这是你的意思是:

,但如果我理解正确的 - 在你__init__.py文件做到这一点。

import os 

__all__ = [] 

for module in os.listdir(os.path.dirname(__file__)): 
    if module != '__init__.py' and module[-3:] == '.py': 
     __all__.append(module[:-3]) 

您要添加在同一个包中的所有文件到__all__

+0

但是这不会导入子模块。也许我没有说清楚,我已经更新了这个问题。 – NeoWang

+0

这个解决方案可以让你从'myPackage import module1'和'module1.funcA()'完成这个工作。你可以在包里添加任意数量的模块而不用改变'__init __。py' – Rcynic

2

只需添加模块名称__all__不会总是达到目的。我遇到过这样的问题,并且还要求将它们添加到__all__以外。这是我想出来的代码,以使其适用于我的情况。我没有任何子包,所以这段代码只能在顶层工作。

modules = glob.glob(os.path.dirname(__file__) + '/*.py') 
__all__ = [] 
for mod in modules: 
    if not str(mod).endswith('__init__.py'): 
    package_prefix = __name__ + '.' 
    module_name = str(mod)[str(mod).rfind('\\') + 1:-3] 
    __all__.append(module_name) 
    __import__(package_prefix + module_name, globals(), locals(), [''])