创建 Python 包时出现导入错误——我应该在哪里设置入口点?

Import errors when creating a Python package -- where should I have my entry point?

(TL;DR) 我正在创建一个 Python 包,但我总是无法导入和理解 python 运行s 脚本如何在 packages/modules 中运行。如何在目录之间正确导入以下目录结构?我应该把我想作为这个应用程序入口点的脚本放在哪里,用户应该如何 运行 它?

我当前的目录结构如下所示:

package_name
├── (venv)
├── __init__.py
├── package_name
│   ├── __init__.py
│   ├── script.py
│   ├── common
│   │   ├── __init__.py
│   │   ├── cfg1.py
│   │   └── cfg2.py
│   ├── core
│   │   ├── __init__.py
│   │   ├── utils1.py
│   │   └── utils2.py
│   └── templates
│       ├── base.txt
│       ├── template1.txt
│       ├── template2.txt
│       ├── ...
│       ├── templateN.txt
├── setup.py
└── tests
    └── test_core
        ├── data
        └── test_core.py

里面 script.py:

from core import utils1, utils2

def main():
    # Parse some args - want the user to supply them from command line
    utils1.thing()
    utils2.another_thing()

if __name__ == "__main__":
    main()

里面 utils1.py:

from package_name.common.cfg1 import allowed_configs
# This fails
# And then the utilities are here

我希望用户能够调用 script.py 并提供命令行参数来执行某些操作。当我 运行:

python3 pathto/package_name/package_name/script.py option1 --arg1 value

在激活我的 virtualenv 后从命令行,我从 utils1.py:

得到一个错误
ModuleNotFoundError: No module named 'package_name.common'

如果我运行它作为一个模块:

python3 -m package_name.package_name.script option1 --arg1 value

我在这一行收到不同的错误:

from core import utils1, utils2

错误:

ModuleNotFoundError: No module named 'core'

现在根据我对 modules/packages/scripts 的研究,我知道我不能 运行 包中的模块作为脚本而不使用 -m 标志。我认为我得到那个错误是有道理的,但我不直观地理解为什么。

我真的不想手动弄乱 Python 路径,但我可以在以下方面使用一些建议:

1) 对于像这样旨在分发给用户并从命令行调用的 Python 包,正确的 structure/layout 是什么?最终用户最终应该如何调用 script.py?

2) 如何在不在脚本中手动设置路径的情况下在子目录之间导入?可能吗?

3) 我还没有 "installed" 带有 setup.py 的包,因为我还没有弄清楚它是如何工作的。修复我的 setup.py 让 packages=find_packages() 可以解决这个问题吗?如果是这样,每次我想测试对我的代码的更改时,我是否需要 运行 setup.py development

我能够通过以下方式让它工作:

我希望能够从命令行 运行 脚本,所以我跟随此页面以了解如何在我的 setup.py 中实现入口点:https://click.palletsprojects.com/en/5.x/setuptools/

我试图添加一个 scripts 关键字,但我不太明白如何让它发挥作用。通过使用 console_scripts 在使用 pip install -e . 安装后,我可以像可执行文件一样直接调用我的脚本。对于其他有同样问题的人,请注意,当我使用 pip 安装它时,我是从包含 setup.py 的目录中安装的(事后看来这是有道理的,但我第一次尝试从顶部安装package_name 目录)

以下内容在我的导入中发生了变化。最初,我有 from core import utils1, utils2 但是当我用 pip 安装包时,它变成了 package_name.core (因为 package_name 是包)。其他出现错误的失败导入路径也是如此;正确的导入是 package_name.common.cfg1

希望这对某人有所帮助!我发现有帮助的参考资料: