Подтвердить что ты не робот

Сделать 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, так как у них есть файл инициализации. спасибо.

4b9b3361

Ответ 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*']),
    ...,
)

Вы также можете тривиально преобразовать его в ленивый генератор.