🔗 高优先级工具已拆分细粒度页:
- pyproject-toml 把 pyproject.toml、requirements.txt、MANIFEST.in、.pypirc、setup.py、setup.cfg 的旧笔记整理到一起。
导航
收录来源
raw/langs/pythons/tools/config_file.rstraw/langs/pythons/tools/config_files/file_pyproject.toml.rstraw/langs/pythons/tools/config_files/file_requirement.txt.rstraw/langs/pythons/tools/config_files/file_MANIFEST.in.rstraw/langs/pythons/tools/config_files/file_.pypirc.rstraw/langs/pythons/tools/config_files/file_setup.py.rstraw/langs/pythons/tools/config_files/file_setup.cfg.rst
条目内容
文件pyproject.toml
spec
- pyproject.toml 文件是用 TOML 编写的。当前指定了三个表,即 [build-system]、[project] 和 [tool]。
- 注意:只有
[build-system]表的requires字段是必需的
当 pyproject.toml 文件不存在时,构建工具应使用下面的示例配置文件作为其默认语义:
[build-system]
# Minimum requirements for the build system to execute.
requires = ["setuptools"]
示例:
[project]
name = "mypackage"
version = "0.0.1"
dependencies = [
"requests",
'importlib-metadata; python_version<"3.8"',
]
[build-system] section
- declare which build backend you use and which other dependencies are needed to build your project.
setuptools示例:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
hatchling示例:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Flit 示例:
[build-system]
requires = ["flit_core>=3.4"]
build-backend = "flit_core.buildapi"
PDM 示例:
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project] section
- specify your project’s basic metadata, such as the dependencies, your name, etc.
Note
As of August 2024, Poetry is a notable build backend that does not use the [project] table, it uses the [tool.poetry] table instead. Also, the setuptools build backend supports both the [project] table, and the older format in setup.cfg or setup.py.
[project]
dependencies = [
"httpx",
"gidgethub[httpx]>4.0.0",
"django>2.1; os_name != 'nt'",
"django>2.0; os_name == 'nt'", # ; 分隔 依赖项 和 条件, 格式: <依赖项> ; <条件>
]
收集示例:
"pywin32>=306; sys_platform == 'win32' or platform_system == 'Windows'"
"pngpaste; sys_platform == 'darwin' and python_version < '3.12'"
示例:
[project]
name = "example_package_YOUR_USERNAME_HERE"
version = "0.0.1"
authors = [
{ name="Example Author", email="author@example.com" },
]
maintainers = [
{name = "Brett Cannon", email = "brett@example.com"}
]
description = "A small example package"
readme = "README.md"
# readme = {file = "README.txt", content-type = "text/markdown"}
# readme = {file = "README.rst", content-type = "text/x-rst"}
license = {file = "LICENSE"}
keywords = ["egg", "bacon", "sausage", "tomatoes", "Lobster Thermidor"]
requires-python = ">=3.8"
# A list of PyPI classifiers that apply to your project.
classifiers = [
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
"Development Status :: 4 - Beta",
# Indicate who your project is intended for
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
# Specify the Python versions you support here.
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
# PyPI will always reject packages with classifiers beginning with Private ::
Private :: Do Not Upload classifier,
]
dynamic metadata
- When a field is dynamic, it is the build backend’s responsibility to fill it. Consult your build backend’s documentation to learn how it does it
setuptools示例:
[project]
dynamic = ["version"]
[tool.setuptools.dynamic]
version = {attr = "package.__version__"}
[project.urls] sub section
允许您列出任意数量的额外链接以在 PyPI 上显示。通常,这可能是源、文档、问题跟踪器等:
[project.urls]
Homepage = "https://github.com/pypa/sampleproject"
Issues = "https://github.com/pypa/sampleproject/issues"
# 如果key带空格需要加引号
"Official Website" = "https://example.com"
[project.optional-dependencies] sub section
[project.optional-dependencies]
gui = ["PyQt5"]
cli = [
"rich",
"click",
]
指定了gui参数,则会安装 PyQt5 依赖库:
pip install your-project-name[gui]
[project.scripts] sub section
To install a command as part of your package, declare it in the [project.scripts] table:
[project.scripts]
spam-cli = "spam:main_cli"
# after installing your project, a spam-cli command will be available.
# Executing this command will do the equivalent of `from spam import main_cli; main_cli()`
[project.gui-scripts] sub section
windows 专用:
[project.gui-scripts]
spam-gui = "spam:main_gui"
Advanced plugins
-
Some packages can be extended through plugins.
-
Examples include Pytest and Pygments.
-
To create such a plugin, you need to declare it in a subtable of [project.entry-points] like this:
[project.entry-points.”spam.magical”] tomatoes = “spam:main_tomatoes”
pipx 示例 :
[project.entry-points."pipx.run"]
greetings = "greetings.cli:app"
[tool] section
- tool-specific subtables, e.g., [tool.hatch], [tool.black], [tool.mypy].
文件requirement.txt
文件内容格式:
# 项目所需的依赖项
flask==2.0.1
requests>=2.25.1,<3.0.0
# 测试依赖项(通过另一个文件包含)
使用 -r 选项可以包含另一个 requirements.txt 文件的内容
-r requirements-test.txt
# 可编辑模式安装当前目录的项目
-e .
# 从Git仓库安装依赖项
-e git+https://github.com/xxx/yyy.git@<branch>#egg=<package_name>
示例:
-e git+https://github.com/psf/requests.git#egg=requests
安装:
pip install -r requirements.txt
导出requirement.txt文件
-
手工写
-
导出当前环境:
pip freeze > ./requirements.txt -
根据源码import 语句生成
pip install pipreqs 使用: pipreqs —use-local ./
注意,此工具不能分析wheel格式的第3方库,故不能发现其使用的依赖 如 django使用的 mysqlclient 不能生成,需要手工添加
离线安装依赖
开发服务器端>>导出并打包依赖包:
pip download -d require -r requirements.txt
之后把require文件夹拷贝到使用服务器
使用服务器 安装依赖:
pip install --no-index --find-links=require -r requirements.txt
MANIFEST.in
- A MANIFEST.in is needed when you need to package additional files that are not automatically included in a source distribution.
Note
However, you may not have to use a MANIFEST.in. For an example, the PyPA sample project has removed its manifest file, since all the necessary files have been included by Setuptools 43.0.0 and newer.
Note
MANIFEST.in does not affect binary distributions such as wheels.
.pypirc
- .pypirc 文件允许您定义 package indexes(即: repo, 存储库) 的配置,这样,无论何时使用
twine或flit上传包,都不必输入 URL、用户名或密码。
示例:
[distutils]
index-servers =
nexus
pypitest
[default]
repository: nexus
[nexus]
repository=http://nexus.zhaoweiguo.com/repository/pypi_hosted/
username=user
password=pwd
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-...
安全
- 使用 keyring 来安全地存储 API 令牌或密码时,目的是避免在 .pypirc 文件中直接写入明文密码。
先通过 keyring 设置密码:
# Python
keyring.set_password("pypi", "__token__", "your-password")
# shell
keyring set https://upload.pypi.org/legacy/ __token__
文件setup.py
主要内容包括:
1. 项目元数据
项目的基本信息,如名称、版本、作者、作者邮箱、描述、URL 等
2. 项目依赖关系
该项目运行所需的第三方库列表,通常以 install_requires 列出
3. 项目打包
配置如何将项目打包为可分发的形式,包括指定包所在的目录、数据文件、脚本等
4. 项目入口点
定义执行入口,指示安装后如何启动或使用该项目
5. 额外依赖
用于指定额外的依赖,例如开发依赖、测试依赖等
示例:
from setuptools import setup, find_packages
# 指定变量
requirements = (here / "requirements.txt").read_text(encoding="utf-8").splitlines()
extras_require = {
"selenium": ["selenium>4", "webdriver_manager", "beautifulsoup4"],
"search-google": ["google-api-python-client==2.94.0"],
}
extras_require["test"] = [
*set(i for j in extras_require.values() for i in j),
"pytest",
]
setup(
# 1. 项目元数据
name="my_project",
version="0.1.0",
author="Your Name",
author_email="your.email@example.com",
description="A short description of your project",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
url="https://github.com/yourusername/my_project",
# 2. 项目依赖关系(自动安装的依赖库)
install_requires=[
"requests>=2.20.0",
"numpy>=1.18.0",
],
# install_requires=requirements,
# 3. 项目打包
packages=find_packages(),
# packages=find_packages(exclude=["contrib", "docs", "examples", "tests*"]),
# packages=find_packages(include=['sample', 'sample.*']),
# packages=["asmk",], # 指定要打包的 Python 包。这里只打包了 asmk 文件夹下的内容。
# package_data: 用于指定与代码相关联的额外文件,例如配置文件、模板、静态资源等
# 这些文件在打包时会被包括在内。它的格式是一个字典,键是包的名称,值是要包含的文件列表
package_data={
"my_project": ["data/*.csv"], # 包含数据文件,例如 CSV 文件
},
# 如果设为 True,则在打包时会包括源代码控制系统中被标记的所有文件
include_package_data=True,
# 尽管配置 package_data 足以满足大多数需求,但在某些情况下,您可能需要将数据文件放在包之外。
data_files=[('my_data', ['data/data_file'])],
# 4. 项目入口点
entry_points={
"console_scripts": [
"my_command=my_project.module:function", # 定义命令行入口
],
},
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6', # 指定 Python 版本要求
# 5. 额外依赖
extras_require=extras_require,
# 声明一个 C 扩展模块,模块名为 asmk.hamming,源码路径是 cython/hamming.c
ext_modules=[Extension("asmk.hamming", ["cython/hamming.c"])], # 编译时会生成 .so 或 .pyd 文件供 Python 调用
# 自定义安装类:InstallWrapper
# 对默认 install 命令的封装,用于安装前检查是否安装了 faiss
# 如果找不到 faiss,就提示错误并终止安装。
# install.run(self): 如果一切正常,继续执行标准的安装流程。
class InstallWrapper(install):
def run(self):
try:
import faiss
except ImportError:
sys.stderr.write("\nERROR: faiss package not installed\n\n")
sys.exit(1)
install.run(self)
# 指定 install 命令时使用我们自定义的 InstallWrapper 类,加入安装前检查逻辑
cmdclass={"install": InstallWrapper,}, #
)
4.项目入口点-entry_points
-
entry_points 是一个字典,键表示入口点的类别,值是一个列表,每个列表项定义一个入口点
-
entry_points 的格式如下:
entry_points = { "<category_name>": [ "<entry_point_1>", "<entry_point_2>", ... ], ... }
category_name是入口点的类别,主要包括:
1. console_scripts:
用于定义命令行脚本,允许你在安装后创建可在命令行中执行的脚本
2. gui_scripts:
与 "console_scripts" 类似,但用于图形用户界面 (GUI) 应用程序
这个入口点会在系统中创建可执行的 GUI 程序,通常在 GUI 环境中运行
3. pytest11:
用于 pytest 插件
定义了 pytest 的扩展点,使你可以创建自定义的 pytest 插件
entry_point_X是具体的入口点定义,格式一般为:
<script_name>=<module_name>:<object_name>
说明:
<script_name> 是入口点的名称
<module_name> 是 Python 模块的名称
<object_name> 是模块中的对象或函数
console_scripts
-
用于命令行脚本
-
格式:
entry_points = { "console_scripts": [ "<script_name>=<module_name>:<object_name>", ], }
说明:
"console_scripts" 指定了命令行脚本类别
"<script_name>" 是命令行中的命令名称
"<module_name>:<object_name>"
表示在命令行中执行模块和对应的函数或对象
gui_scripts
-
用于 GUI 脚本
-
格式:
entry_points = { "gui_scripts": [ "my_gui_command=my_gui_module:main", ], }
说明:
"gui_scripts" 用于定义 GUI 应用程序入口点。
"my_gui_command" 是命令行中用于启动 GUI 应用程序的命令。
"my_gui_module:main" 指定 GUI 程序的入口函数。
实例
./files/setup.py.MetaGPT.py
文件setup.cfg
示例:
[metadata]
name = mypackage
version = 0.0.1
[options]
install_requires =
requests
importlib-metadata; python_version < "3.8"
- 简洁性:setup.cfg 是一个 INI 格式的配置文件,适合存储静态的配置信息。它比 setup.py 更简洁,易于阅读和维护。
- 标准化:符合 PEP 517 和 PEP 518 标准,推荐用于现代 Python 包的构建。
- 工具支持:许多现代构建工具(如 setuptools 和 flit)支持 setup.cfg,并且可以自动处理许多常见的构建任务。
与 setup.py 和 pyproject.toml 对比
pyproject.toml:
[project]
name = "mypackage"
version = "0.0.1"
dependencies = [
"requests",
'importlib-metadata; python_version<"3.10"',
]
setup.cfg:
[metadata]
name = mypackage
version = 0.0.1
[options]
install_requires =
requests
importlib-metadata; python_version<"3.10"
setup.py:
from setuptools import setup
setup(
name='mypackage',
version='0.0.1',
install_requires=[
'requests',
'importlib-metadata; python_version<"3.10"',
],
)