如何通过pyproject.toml(Hatch等工具)在venv/bin定义可安装脚本
问题
我在用Hatch打包Python包时遇到了问题,想知道如何定义可通过pip安装的脚本,具体需求是:使用python -m build构建包时,将bin/open_foo_bar.py安装到虚拟环境的bin目录(如(virtual env)/bin),而非site-packages/bin目录。
我的包结构(执行python -m build生成dist目录后)如下:
pypi_package/ ├── bin │ └── open_foo_bar.py ├── dist │ ├── foo-0.1.0-py3-none-any.whl │ └── foo-0.1.0.tar.gz ├── pyproject.toml ├── README.md └── test_pkg ├── foolib.py └── __init__.py
目前bin/open_foo_bar.py会被安装到./lib/python3.10/site-packages/bin/open_foo_bar.py,不符合预期。
当前的pyproject.toml配置:
[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "FOO" version = "0.1.0" authors = [ { name="Mr Foo", email="foo@bar.com" }, ] description = "a Foo bar without drinks" readme = "README.md" requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ] dependencies = [ 'requests' ] [project.urls] "Homepage" = "http://footopia.s/howto_foo"
之前使用setup.py的scripts配置可轻松实现该需求:
setuptools.setup( ... scripts=['bin/script1'], ... )
解决方案
方法1:使用PEP 621标准的[project.scripts]配置
在pyproject.toml的[project]区块下添加[project.scripts]配置,绑定脚本名称与入口函数:
[project.scripts] open_foo_bar = "bin.open_foo_bar:main"
说明:此方式要求open_foo_bar.py中存在一个可执行的main函数(也可指定其他函数作为入口)。安装后,可直接通过命令open_foo_bar调用脚本逻辑。
方法2:直接沿用原有脚本的Hatchling专属配置
若不想修改原有脚本添加入口函数,可在pyproject.toml中添加Hatchling的wheel构建配置,直接指定脚本路径:
[tool.hatch.build.targets.wheel.scripts] open_foo_bar = "bin/open_foo_bar.py"
此配置会将bin/open_foo_bar.py直接安装到虚拟环境的bin目录(Windows系统下为Scripts目录),自动处理可执行权限与shebang,同样可通过open_foo_bar命令直接调用。
验证安装结果
构建并安装包后,通过以下命令验证路径:
# Linux/macOS which open_foo_bar # Windows PowerShell Get-Command open_foo_bar
返回的路径应指向虚拟环境的bin(或Scripts)目录,而非site-packages下的路径。
内容的提问来源于stack exchange,提问作者Peter Moore

