Я пытаюсь упаковать небольшое приложение Python 3.9 в файл дистрибутива программного обеспечения .tar.gz
(также известный как «sdist»).
Мой код имеет такую структуру:
my-code
PackageA
PackageB
Module1.py
__init__.py
__init__.py
setup.py
Мой файл setup.py
выглядит так:
from setuptools import find_packages, setup
setup(
name = "my-code",
version = "0.1",
install_requires=[],
packages=find_packages(include=["PackageA.PackageB"]),
include_package_data=True,
description = "My Code"
)
Когда я запускаю python setup.py sdist --formats=gztar
, я успешно получаю my-code-0.1.tar.gz
файл и вижу, что он содержит мои .py
файлы.
Однако, когда я запускаю pip install my-code-0.1.tar.gz
, кажется, что pip
не компилирует и не развертывает мои .py
файлы. т.е. когда я устанавливаю в venv
и просматриваю каталог Lib/site-packages
для venv
, я вижу только каталог с именем my_code-0.1-py3.9.egg-info
, а моего кода в нем нет. Попытки импортировать или запустить мой модуль, который находится в PackageA.PackageB
, не увенчались успехом.
Мой вопрос - Почему мой код не собирается и не устанавливается pip install
и как это исправить?
🤔 А знаете ли вы, что...
Python является интерпретируемым языком программирования.
TL;DR, потому что find_packages(include=["PackageA.PackageB"])
отфильтрует родительский PackageA
, поэтому он не включен в установку. Просто используйте
setup(
packages=find_packages(),
...
)
и все будет хорошо.
Более длинное объяснение состоит в том, что аргумент include
не означает «включать в дополнение к тому, что find_packages()
находит». Это означает «включать только пакеты, найденные find_packages()
, которые находятся в списке фильтров include
», поэтому он может только уменьшить выбор пакета. Сравните вывод
$ python -c "from setuptools import find_packages as f; print(f())"
['PackageA', 'PackageA.PackageB']
против
$ python -c "from setuptools import find_packages as f; print(f(include=['PackageA.PackageB']))"
['PackageA.PackageB']
Поскольку PackageA
не включен, PackageA/__init__.py
будет опущен в исходном дистрибутиве, что фактически удалит свойство пакета из PackageA
- в tar-архиве теперь это будет обычный каталог. Бег pip install mydist.tar.gz
больше не найдет PackageA
, поэтому PackageA.PackageB
тоже нельзя найти. Следовательно, ничего не будет установлено. Раздел Автоматическое обнаружение пакетов в документах setuptools
содержит краткое упоминание аргументов include
и exclude
для find_packages()
, но IMO гораздо более полезна строка документации функции:
>>> from setuptools import find_packages
>>> help(find_packages)
find(where='.', exclude=(), include=('*',)) method of builtins.type instance
Return a list all Python packages found within directory 'where'
...
'include' is a sequence of package names to include. If it's
specified, only the named packages will be included. If it's not
specified, all found packages will be included. 'include' can contain
shell style wildcard patterns just like 'exclude'.