【问题标题】:ModuleNotFoundError when using setup.cfg and version accessed with attr使用 setup.cfg 和使用 attr 访问的版本时出现 ModuleNotFoundError
【发布时间】:2020-01-31 19:34:04
【问题描述】:

我有一个 Python 包,其结构如下:

├── setup.cfg
├── setup.py
└── src
    └── myproject
        ├── base.py
        ├── __init__.py
        └── version.py

setup.cfg中,版本是用attr定义的:

[metadata]
name = myproject
version = attr: myproject.version.__version__

version.py 很简单:

__version__ = "1.2.3"

包的依赖项列在setup.cfg 中。另一方面,包的顶层__init__.py 导入包的一些对象:

from myproject.base import Stuff

__all__ = ["Stuff"]

而且,很明显,base.py 从依赖项中导入了一些对象。

现在的问题是,如果我在未安装依赖项的情况下尝试使用python setup.py,我有一个ModuleNotFoundError/ImportError,因为__init__.py 导入了导入这些依赖项的对象(这非常适合案例6在the Python documentation on managing version file):

python setup.py --version
Traceback (most recent call last):
<snip>
ModuleNotFoundError: No module named 'dependency_module'

这使得无法安装依赖项。那么针对版本文件的最佳策略应该是什么?

到目前为止,我已经在__init__.py 上尝试过这种奇怪的异常处理方法:

try:
    from myproject.base import Stuff
except ImportError:
    pass

有没有更好的方法?还是其他方法?

【问题讨论】:

  • 您的 setuptools 版本是多少? version = attr: myproject.version.__version__ 至少应该是 39.2.0 才能工作。
  • 版本高于40.0.0。
  • 看起来像 github.com/pypa/setuptools/issues/1724 。我真的很惊讶,从我的角度来看,它首先破坏了拥有version = attr: myproject.version.__version__ 功能的点。我有点迷茫……
  • 是的,我完全同意!这个错误绝对是合乎逻辑的,但如果你使用attr:,这是不可避免的。
  • 看来attr:的情况同时有所改善:github.com/pypa/setuptools/pull/1753 -- 好像已经在v46.4.0 on 16 May 2020发布了

标签: python-3.x setuptools setup.py


【解决方案1】:

您似乎遇到了此处提交的问题:https://github.com/pypa/setuptools/issues/1724

最好将版本号写入VERSION.txt,从setup.cfgversion = file: VERSION.txt 读取它,然后从__init__.pyimport importlib_metadata; __version__ = importlib_metadata.version('myproject') 加载它。


更新

importlib_metadata is on PyPI for current Python versions 并以Python 3.8 in the standard library as importlib.metadata 开头。

综上所述,可以重新考虑是否需要将版本字符串放在单独的文件中。由于可以直接从代码中读取版本字符串,因此version.pyVERSION.txt 的用途可能会丢失。

或者,我倾向于将我的设置脚本改为read the version string from the changelog


更新 2020 年 11 月 3 日

看起来attr: 的情况在此期间有所改善,这要感谢change。如果可能,使用 attr: 实际上不会导入代码,因此问题中最初报告的 ModuleNotFoundError 不应再发生。已在v46.4.0 on 16 May 2020发布。

【讨论】:

  • 这非常优雅地解决了这个问题。附带说明一下,importlib_metadata 是您必须安装的第三方软件包。从 Python 3.8 开始,它将作为 importlib.metadata 成为标准库的一部分。
  • 是的。我用这个信息和更多信息更新了答案。
  • 您关于最终将版本号存储在setup.cfg 而不是专用文件中的最后评论也非常正确。
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 2021-03-30
  • 2020-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-08-02
  • 1970-01-01
  • 2021-10-28
相关资源
最近更新 更多