python - 运行 setup.py 时如何获取 Python 轮子的文件名?
问题描述
我有一个使用以下命令创建 Python 轮子的构建过程:
python setup.py bdist_wheel
构建过程可以在许多平台(Windows、Linux、py2、py3 等)上运行,我想保留默认输出名称(例如mapscript-7.2-cp27-cp27m-win_amd64.whl
)以上传到 PyPI。
有没有办法获取生成的轮子的文件名(例如mapscript-7.2-cp27-cp27m-win_amd64.whl
)并保存到一个变量中,这样我就可以稍后在脚本中安装轮子进行测试?
理想情况下,解决方案将是跨平台的。我目前的方法是尝试清除文件夹,列出所有文件并选择列表中的第一个(也是唯一一个)文件,但这似乎是一个非常hacky的解决方案。
解决方案
setuptools
如果您使用setup.py
脚本构建wheel 发行版,您可以使用该bdist_wheel
命令查询wheel 文件名。这种方法的缺点是它使用bdist_wheel
的私有 API,因此wheel
如果作者决定更改它,代码可能会在包更新时中断。
from setuptools.dist import Distribution
def wheel_name(**kwargs):
# create a fake distribution from arguments
dist = Distribution(attrs=kwargs)
# finalize bdist_wheel command
bdist_wheel_cmd = dist.get_command_obj('bdist_wheel')
bdist_wheel_cmd.ensure_finalized()
# assemble wheel file name
distname = bdist_wheel_cmd.wheel_dist_name
tag = '-'.join(bdist_wheel_cmd.get_tag())
return f'{distname}-{tag}.whl'
该wheel_name
函数接受您传递给该setup()
函数的相同参数。示例用法:
>>> wheel_name(name="mydist", version="1.2.3")
mydist-1.2.3-py3-none-any.whl
>>> wheel_name(name="mydist", version="1.2.3", ext_modules=[Extension("mylib", ["mysrc.pyx", "native.c"])])
mydist-1.2.3-cp36-cp36m-linux_x86_64.whl
请注意,本机库(mysrc.pyx
或native.c
在上面的示例中)的源文件不必存在即可组装车轮名称。这在本机库的源不存在的情况下很有帮助(例如,您稍后通过 SWIG、Cython 或其他方式生成它们)。
这使得在定义分发元数据的脚本中wheel_name
易于重用:setup.py
# setup.py
from setuptools import setup, find_packages, Extension
from setup_helpers import wheel_name
setup_kwargs = dict(
name='mydist',
version='1.2.3',
packages=find_packages(),
ext_modules=[Extension(...), ...],
...
)
file = wheel_name(**setup_kwargs)
...
setup(**setup_kwargs)
如果你想在设置脚本之外使用它,你必须自己组织对setup()
args 的访问(例如从脚本中读取它们setup.cfg
或其他)。
这部分大致基于我对setuptools 的其他回答,提前知道原生库的轮文件名
poetry
如果您使用,事情可以简化很多(它实际上是单行),poetry
因为所有相关的元数据都存储在pyproject.toml
. 同样,这使用了一个未记录的 API:
from clikit.io import NullIO
from poetry.factory import Factory
from poetry.masonry.builders.wheel import WheelBuilder
from poetry.utils.env import NullEnv
def wheel_name(rootdir='.'):
builder = WheelBuilder(Factory().create_poetry(rootdir), NullEnv(), NullIO())
return builder.wheel_filename
rootdir
参数是包含您的pyproject.toml
脚本的目录。
flit
AFAIKflit
无法使用本机扩展构建轮子,因此它只能为您提供 purelib 名称。flit
不过,如果您的项目用于分发构建,它可能会很有用。请注意,这也使用了未记录的 API:
from flit_core.wheel import WheelBuilder
from io import BytesIO
from pathlib import Path
def wheel_name(rootdir='.'):
config = str(Path(rootdir, 'pyproject.toml'))
builder = WheelBuilder.from_ini_path(config, BytesIO())
return builder.wheel_filename
实施您自己的解决方案
我不确定这是否值得。尽管如此,如果您想选择这条路径,packaging.tags
请在找到一些旧的弃用的东西之前考虑使用,甚至决定自己查询平台。不过,您仍然需要使用私人物品来组装正确的车轮名称。
推荐阅读
- git - git remote - 如何更改引用
- flutter - Flutter Charts - 标记颜色与系列颜色不匹配
- c# - 为什么锁需要 C# 中的实例?
- nginx - 在 NGINX 中只允许本地网络访问子域
- centos - centos 8包安装中的“错误:冲突请求”
- c++ - 确定某物是否是字谜的功能问题
- c++ - 带Args的reference_wrappers类型推演
- android - 在 Android Studio 项目中集成 Firestore 时出现致命错误
- discord.js - Quick.db unwarn 命令取消警告成员中的所有警告
- php - Microsoft Graph API - 将文件上传到一个驱动器 - 无法读取 JSON 请求负载。请确保内容-T