Упаковка python проект с несколькими каталогами - PullRequest
1 голос
/ 12 февраля 2020

Мне нужны пояснения по работе с функциями setuptools и find_packages. У меня есть такая структура проекта:

├── project_dir_1
│   ├── module.py
│   ├── __init__.py
├── my_project
│   ├── cli.py
│   ├── subdir1
│   │   ├── __init__.py
│   │   ├── module.py
│   ├── conf
│   │   ├── module.py
│   │   ├── params
│   │   │   ├── config.yml
│   │   ├── __init__.py
│   ├── subdir2
│   │   ├── module.py
│   ├── __init__.py
│   └── version.py
├── project_dir_2
│   ├──  subdir1
│   │   ├── module.py
│   │   ├── __init__.py
│   ├── __init__.py
├── README.md
├── requirements.txt
├── setup.py
└── tests
    └── test_main.py

На самом деле весь мой код в каталоге my_project, и у меня также есть два дополнительных каталога project_dir_1 и project_dir_2, которые содержат необходимые внешние модули, откуда я должен делать импорт как в коде пакета, так и в коде другого проекта, где этот пакет будет установлен в venv. У меня есть сценарий установки, подобный следующему:

setup(
    name='my_project',
    version='0.0.1',
    description='Python library.',
    license='license',
    author='me',
    author_email='my_email',
    entry_points={'console_scripts': ['my_project=my_project.cli:main']},
    python_requires='>=3.7',
    packages=find_packages(
        include=['my_project', 'project_dir_1', 'project_dir_2', 'my_project.*', 'project_dir_1.*', 'project_dir_2.*']
    ),
    install_requires=list(open(join(dirname(__file__), 'requirements.txt')).read().split()),
)

Когда я активирую venv в другой папке проекта и пытаюсь установить пакет из папки root, например python ..\package_root\setup.py install, все выглядит нормально во время установки. И pip list показывает все зависимости и my_project 0.0.1. Но если я пытаюсь импортировать что-то из my_project с помощью интерпретатора venv, я получаю сообщение об ошибке: ModuleNotFoundError: No module named 'my_project'. Тот же результат, если я пытаюсь импортировать что-то вроде from project_dir_1 import module, что также необходимо. Также, когда я просто запускаю my_project из адресации оболочки в cli, я получаю сообщение об ошибке:

Traceback (most recent call last):
  File "/home/developer/another_project/env/bin/my_project", line 11, in <module>
    load_entry_point('my_project==0.0.1', 'console_scripts', 'my_project')()
  File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2852, in load_entry_point
    return ep.load()
  File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2443, in load
    return self.resolve()
  File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2449, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
ModuleNotFoundError: No module named 'my_project'

Итак, как правильно организовать эту сложную структуру проекта и включить весь необходимый код в setup.py, чтобы получить setuptools правильно установить пакет? Мне нужно немного лучше понять упаковку python проектов, но я все еще не могу получить ответы на этот вопрос из-за поиска документов.

1 Ответ

1 голос
/ 14 февраля 2020

find_packages разрешит пути относительно текущего рабочего каталога, поэтому вызов его вне проекта root dir фактически ничего не установит (проверьте, видите ли вы какие-либо установленные источники, например, запустив

$ pip show -f my_project

Бьюсь об заклад, ничего не будет в списке). Вы должны принудительно переключиться на проект root dir в скрипте установки, например, добавьте линию magi c в ваш скрипт установки:

# setup.py

import os
from setuptools import setup

# old-style for python 2
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

# new style for python 3
from pathlib import Path
os.chdir(Path(__file__).parent.absolute())

setup(...)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...