在 setup.py 中包含来自根级别的文件
Include file from root level in setup.py
我正在尝试在我们的工作环境中使用 bamboo pipeline 构建一个 python 包。
要触发构建,我必须包含一个包含版本号的文件 build.info.txt
。
该文件位于存储库的顶层,因此存储库结构如下
build.info.txt
setup.py
MANIFEST.in
README.md
package/
__init__.py
file1.py
file2.py
文件build.info.txt
有版本号
version=x.y.z
我想用这个文件来触发版本号,因此在 __init__.py
我包含了一个简单的解析器
from pathlib import Path
path = Path(__file__).absolute().parent / "build.info.txt"
__version__ = open(path).readline()[0].split("=")[-1]
这在本地模式下工作正常。但是,当我创建一个包并将其推送到我们的 pypi 服务器时,我在运行时收到以下错误(即 pip install package
有效):
FileNotFoundError: [Errno 2] No such file or directory: '</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt'
我更改了 setup.py
的行为(我使用 setuptools
)包括:
setup(**other_params, package_data={"": ["../build.info.txt"]}, include_package_data=True)
而 MANIFEST.in
看起来像
include build.info.txt
问题是 build.info.txt
使用 pip install
位于顶层:
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt
这个文件在几个包之间共享,而我想把这个文件放在
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/<PACKAGE>/build.info.txt
(然后我必须在 __init__
中管理解析器才能解析正确的文件,但这很简单)
我该如何管理?
谢谢
我的建议是使用importlib.metadata
阅读项目的版本。
有人试图将 PEP 396 中设置 __version__
的约定形式化和标准化,但从未得到完全接受。而且现在这种习惯也消失了,因为对它的需求不再那么紧迫,感谢 importlib.metadata
。因此,您可以完全删除 __version__
,并且想要知道您的应用程序或库的版本号的第 3 方代码可以使用 importlib.metadata.version('MyProject')
来读取它。
如果您坚持要在您的图书馆中拥有 __version__
,您可以扭转局面并在您的 __init__.py
中执行以下操作:
__version__ = importlib.metadata.version('MyProject')
旁白:
如果您坚持使用文件 build-info.txt
,那么您可以在包中对其进行符号链接,例如 package/build-info.txt
(链接到 build-info.txt
) ,并且 __init__.py
可以在 run-time.
读取该文件
- 或者,如评论中所建议的那样,符号链接
build-info.txt
到 package/build_info.py
,并在 __init__.py
中:from build_info import version as __version__
(假设该文件的内容也是有效的 Python 语法)。
你不应该使用 __file__
来读取包数据资源,这是不可靠的,使用 importlib.resources
代替(它会以更简洁的方式执行此操作,如果需要注意提取文件以防包被压缩等)。
有一些工具可以解决所有这些版本号问题,setuptools-scm
浮现在脑海中,可能满足您的需求。
我正在尝试在我们的工作环境中使用 bamboo pipeline 构建一个 python 包。
要触发构建,我必须包含一个包含版本号的文件 build.info.txt
。
该文件位于存储库的顶层,因此存储库结构如下
build.info.txt
setup.py
MANIFEST.in
README.md
package/
__init__.py
file1.py
file2.py
文件build.info.txt
有版本号
version=x.y.z
我想用这个文件来触发版本号,因此在 __init__.py
我包含了一个简单的解析器
from pathlib import Path
path = Path(__file__).absolute().parent / "build.info.txt"
__version__ = open(path).readline()[0].split("=")[-1]
这在本地模式下工作正常。但是,当我创建一个包并将其推送到我们的 pypi 服务器时,我在运行时收到以下错误(即 pip install package
有效):
FileNotFoundError: [Errno 2] No such file or directory: '</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt'
我更改了 setup.py
的行为(我使用 setuptools
)包括:
setup(**other_params, package_data={"": ["../build.info.txt"]}, include_package_data=True)
而 MANIFEST.in
看起来像
include build.info.txt
问题是 build.info.txt
使用 pip install
位于顶层:
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt
这个文件在几个包之间共享,而我想把这个文件放在
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/<PACKAGE>/build.info.txt
(然后我必须在 __init__
中管理解析器才能解析正确的文件,但这很简单)
我该如何管理?
谢谢
我的建议是使用importlib.metadata
阅读项目的版本。
有人试图将 PEP 396 中设置 __version__
的约定形式化和标准化,但从未得到完全接受。而且现在这种习惯也消失了,因为对它的需求不再那么紧迫,感谢 importlib.metadata
。因此,您可以完全删除 __version__
,并且想要知道您的应用程序或库的版本号的第 3 方代码可以使用 importlib.metadata.version('MyProject')
来读取它。
如果您坚持要在您的图书馆中拥有 __version__
,您可以扭转局面并在您的 __init__.py
中执行以下操作:
__version__ = importlib.metadata.version('MyProject')
旁白:
如果您坚持使用文件
读取该文件build-info.txt
,那么您可以在包中对其进行符号链接,例如package/build-info.txt
(链接到build-info.txt
) ,并且__init__.py
可以在 run-time.- 或者,如评论中所建议的那样,符号链接
build-info.txt
到package/build_info.py
,并在__init__.py
中:from build_info import version as __version__
(假设该文件的内容也是有效的 Python 语法)。
- 或者,如评论中所建议的那样,符号链接
你不应该使用
__file__
来读取包数据资源,这是不可靠的,使用importlib.resources
代替(它会以更简洁的方式执行此操作,如果需要注意提取文件以防包被压缩等)。有一些工具可以解决所有这些版本号问题,
setuptools-scm
浮现在脑海中,可能满足您的需求。