如何将 setup.py console_script 与本机命名空间包一起使用

How to use setup.py console_script with native namespace packages

我无法为使用 Python 命名空间包结构的 Python 包定义 console_scripts

我正在关注 Python 3.8.2 中的 Python packaging document. Specifically, I am using native namespace packaging 中概述的 Python 命名空间包。

我是这样创建我的项目的:

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 install -e src/main/python/mynamespace-mypackage 使用 pip 安装我的项目时,包安装成功。但是,当我从命令行调用 do-some-stuff 时,我得到 ModuleNotFoundError: No module named 'mypackage'.

我还尝试将 console_scripts 修改为:


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

但是当我从命令行 运行 do-some-stuff 时,这也会给出 ModuleNotFoundError: No module named 'mynamespace.mypackage

我应该如何定义程序的入口点以正确指向包的 __main__:main 函数?非常感谢任何帮助。

可能的解决方法:

基于setuptools documentation,如果我将__init__.py添加到mynamespace目录,内容如下

__import__("pkg_resources").declare_namespace(__name__)

并通过添加 namespace_packages=["mynamespace"] 修改 setup.py,入口点有效。 我可以确认这解决了我的问题。但是,我认为这并不理想。 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!")

事实证明问题是一个过时的 setuptools 库。我正在使用 setuptools-41.2.0。我升级到 setuptools-46.1.3,现在我的最小示例按预期工作。不需要解决方法。

pip install -U setuptools