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, know in advance the wheel filename of a native library的其他回答
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
AFAIK flit 无法使用本机扩展构建轮子,因此它只能为您提供 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,然后再找到一些旧的已弃用的东西,甚至决定自己查询平台。不过,您仍然需要使用私人物品来组装正确的车轮名称。