在Python中使distutils自动查找包
当在Python的distutils
中的setup.py
中描述python包时,是否有办法让它自动获取每个包含__init__.py
目录,并将其作为子包装?
即如果结构是:
mypackage/__init__.py mypackage/a/__init__.py mypackage/b/__init__.py
我想避免这样做:
packages = ['mypackage', 'mypackage.a', 'mypackage.b']
而只是做:
packages = ['mypackage']
并让它自动find像a
和b
类a
东西,因为它们有一个init文件。 谢谢。
最简单的方法(我知道)是使用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 ... )
我build议使用setuptools提供的find_packages()函数,例如:
from setuptools import setup, find_packages
然后呢
packages=find_packages()
同dm76的答案,只是我也有我的回购testing,所以我使用:
from setuptools import find_packages packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
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() ... )
直接replacesetuptools.find_packages()
:
from pkgutil import walk_packages from fnmatch import fnmatch as wc_match from itertools import chain def find_packages(where, exclude=None): if not exclude: exclude = () if isinstance(where, str): where = (where, ) ret_list = [] for name in chain.from_iterable(map(lambda w: (n for _, n, ispkg in w if ispkg), (walk_packages(p) for p in where))): if not any(wc_match(name, p) for p in exclude): ret_list.append(name) return tuple(ret_list) find_packages(".", exclude=['*.test*']) find_packages((".", "lib", "src"), exclude=['*.test*']) from distutils.core import setup setup( ..., packages=find_packages(".", exclude=['*.test*']), ..., )
你也可以简单地把它转换成懒惰的生成器。