2013-02-15 71 views
0

我在我的模块的__init__.py中使用下面的代码来填充__all__,如果有更有效的方法,我就会徘徊。有任何想法吗?在__init__.py中递归填充__all__

import fnmatch 
import os 

__all__ = [] 
for root, dirnames, filenames in os.walk(os.path.dirname(__file__)): 
    root = root[os.path.dirname(__file__).__len__():] 
    for filename in fnmatch.filter(filenames, "*.py"): 
     __all__.append(os.path.join(root, filename[:-3])) 
+0

如果你想导出所有东西,你真的需要'__all__'吗?如果未定义'__all__',默认行为是导出所有内容。 – alexis 2013-02-15 22:22:07

+0

@alexis确实如此,但我希望能够*排除*一些,所以我想用所有内容填充__all__,然后删除那些我不想公开的内容。 – 2013-02-16 12:29:28

回答

2

您可能不应该这样做:默认行为import是相当灵活的。如果你不想要一个模块(或任何其他变量)被自动导出,给它一个以_开头的名字,并且python不会导出它。这是标准的python方式,重新发明轮子被认为是和谐的。另外,不要忘记,除模块之外的其他东西可能需要导出;一旦你设置了__all__,你还需要找到并导出它们。

但是,您仍然要问如何最好地生成可导出模块的列表。既然你不能导出什么是不存在的,我只是检查已知的主模块的模块是什么你自己:

basedir = os.path.dirname(__file__) 
for m in sys.modules: 
    if m in locals() and not m.startswith('_'): # Only export regular names 
     mod = locals()[m] 
     if '__file__' in mod.__dict__ and mod.__file__.startswith(basedir): 
      print m 

sys.modules包括每一个蟒蛇已加载模块的名称,其中包括许多有没有被导出到你的主模块 - 所以我们检查它们是否在locals()

这比扫描文件系统更快,并且比您假设目录树中的每个.py文件都以某种方式最终成为顶级子模块更为强大。自然地,您应该在__init__.py的末尾附近运行此代码,当所有内容都已加载完毕时。