Сделать distutils в Python автоматически найти пакеты
При описании пакета python в setup.py
в distutils
в Python существует ли способ сделать так автоматически получить каждый каталог с __init__.py
в нем и включить его в качестве подпакета?
т.е. если структура:
mypackage/__init__.py
mypackage/a/__init__.py
mypackage/b/__init__.py
Я хочу избежать:
packages = ['mypackage', 'mypackage.a', 'mypackage.b']
и вместо этого просто выполните:
packages = ['mypackage']
и автоматически найдет такие вещи, как a
и b
, так как у них есть файл инициализации. спасибо.
Ответы
Ответ 1
Самый простой способ (я знаю) использовать 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 ...
)
Ответ 2
Я бы рекомендовал использовать функцию find_packages(), доступную с помощью setuptools, например:
from setuptools import setup, find_packages
а затем do
packages=find_packages()
Ответ 3
То же, что и ответ dm76, просто у меня также есть тесты в моем репо, поэтому я использую:
from setuptools import find_packages
packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
Ответ 4
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()
...
)
Ответ 5
Замена замены setuptools.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*']),
...,
)
Вы также можете тривиально преобразовать его в ленивый генератор.