Как использовать setup.py console_script с пакетами собственного пространства имен - PullRequest
2 голосов
/ 01 мая 2020

Я не могу определить console_scripts для моего Python пакета, который использует структуру пакетов пространства имен Python.

Я следую пакетам пространства имен Python, указанным в документе Python . В частности, я использую нативную упаковку пространства имен в Python 3.8.2.

Я создал свой проект следующим образом:

src
└── main
   └── python
      └── mynamespace-mypackage
         ├── mynamespace
         │  └── mypackage
         │     ├── __init__.py
         │     ├── __main__.py
         │     ├── module_a.py
         │     └── module_b.py
         └── setup.py

В setup.py, Я пишу:


#!/usr/bin/env python3

from setuptools import setup, find_namespace_packages

PACKAGE = "mynamespace-mypackage"
VERSION = "0.1a"

setup(
    name=PACKAGE,
    version=VERSION,
    packages=find_namespace_packages(include=["mynamespace.*"]),
    description="My fancy package",
    entry_points={
        "console_scripts": {
            "do-some-stuff = mypackage.__main__:main"
        }
    }
)

Когда я устанавливаю свой проект с помощью pip, вызывая pip install -e src/main/python/mynamespace-mypackage, пакет успешно устанавливается. Однако когда я вызываю do-some-stuff из командной строки, я получаю ModuleNotFoundError: No module named 'mypackage'.

Я также пытался изменить console_scripts на:


    entry_points={
        "console_scripts": {
            "do-some-stuff = mynamespace.mypackage.__main__:main"
        }
    }

, но это также дает ModuleNotFoundError: No module named 'mynamespace.mypackage когда я запускаю do-some-stuff из командной строки.

Как мне определить точку входа моей программы, чтобы правильно указывать на функцию __main__:main моего пакета? Любая помощь приветствуется.

Потенциальный обходной путь:

На основе setuptools документация , если я добавлю __init__.py в mynamespace каталог с следующее содержание

__import__("pkg_resources").declare_namespace(__name__)

И измените setup.py, добавив namespace_packages=["mynamespace"], точки входа работают. Я могу подтвердить, что это решает мою проблему. Однако, на мой взгляд, это не идеально. В документации по упаковке Python прямо указано, что при использовании собственной упаковки не следует добавлять __init__.py в каталог пространства имен.

Минимальный воспроизводимый пример:

src/main/python/mynamespace-mypackage/mynamespace/mypackage/__init__.py:

#!/usr/bin/env python3

from .module_a import Hello
from .module_b import GoodBye

__all__ = ["Hello", "GoodBye"]

src/main/python/mynamespace-mypackage/mynamespace/mypackage/__main__.py:

#!/usr/bin/env python3

from . import Hello, GoodBye

def main() -> None:
    h = Hello()
    h.say_hi()
    g = GoodBye()
    g.say_bye()

if __name__ == "__main__":
    main()

src/main/python/mynamespace-mypackage/mynamespace/mypackage/module_a.py:

#!/usr/bin/env python3


class Hello:
    def say_hi(self) -> None:
        print("Hello!")

src/main/python/mynamespace-mypackage/mynamespace/mypackage/module_b.py:

#!/usr/bin/env python3


class GoodBye:
    def say_bye(self) -> None:
        print("Good Bye!")

1 Ответ

0 голосов
/ 04 мая 2020

Оказывается, проблема была устаревшей setuptools библиотеки. Я использовал setuptools-41.2.0. Я обновился до setuptools-46.1.3 и теперь мой минимальный пример работает, как и ожидалось. Нет необходимости в обходном пути.

pip install -U setuptools
...