2012-10-19 35 views
35

在Python中使用setup.pydistutils中描述python包时,是否有办法让它自动获取每个包含__init__.py的目录并将其作为子包装?在Python中使distutils自动找到包

也就是说,如果结构为:

mypackage/__init__.py 
mypackage/a/__init__.py 
mypackage/b/__init__.py 

我想避免这样做:

packages = ['mypackage', 'mypackage.a', 'mypackage.b'] 

,而是只是做:

packages = ['mypackage'] 

,并自动找到的东西像ab,因为它们有一个init文件。谢谢。

+0

只要确保你不要让你这样做之前建立在你的包结构的任何垃圾堆积。 – asmeurer

回答

13

最简单的方法(即我所知道的)是使用pkgutil.walk_packages产生的包:

from distutils.core import setup 
from pkgutil import walk_packages 

import mypackage 

def find_packages(path=__path__, prefix=""): 
    yield prefix 
    prefix = prefix + "." 
    for _, name, ispkg in walk_packages(path, prefix): 
     if ispkg: 
      yield name 

setup(
    # ... snip ... 
    packages = list(find_packages(mypackage.__path__, mypackage.__name__)), 
    # ... snip ... 
) 
+1

有可能(实际上,最有可能*是*)更好的方法来做到这一点......我只是不知道他们(还):-) –

+7

set_unitools的find_packages()基本上完全一样,请参阅我的回答 – dm76

+1

@ dm76是的,但OP是要求distutils,而不是setuptools。我错过了什么吗? – Paolo

98

我会建议使用find_packages()提供的功能与setuptools如:

from setuptools import setup, find_packages 

然后做

packages=find_packages() 
+1

请注意,'find_packages()'没有找到> 3.3样式no-__init__.py包。有关此问题的票据位于https://bitbucket.org/pypa/setuptools/issue/97。因此,现在需要在'find_packages()'auto collection的包中添加__init __。py'文件,或者必须在'packages'中明确地命名它们。 – Iodnas

+1

更新:即使明确的列表导致问题,如果__init __。py'文件没有在Python 3.3上使用('包init文件'mymod/mysubmod/__ init__.py'找不到(或不是普通文件)')。 – Iodnas

2
import re, os 
def find_packages(path='.'): 
    ret = [] 
    for root, dirs, files in os.walk(path): 
     if '__init__.py' in files: 
      ret.append(re.sub('^[^A-z0-9_]+', '', root.replace('/', '.'))) 
    return ret 

setup(
... 
packages = find_packages() 
... 
) 
15

同dm76答案,只是我也有我的回购协议的测试,所以我用:

from setuptools import find_packages 

packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),