创建 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
希望这对某人有所帮助!我发现有帮助的参考资料:
(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
希望这对某人有所帮助!我发现有帮助的参考资料: