[python]python使用setup.cfg打一个wheel

0. 目的

工作中发现openstack的setup.cfg用来管理wheel包,现在来写一个demo测试下此功能

0.1 介绍

在 Python 中,setup.cfg 是一个配置文件,用于定义包的元数据和构建选项。它通常与 setup.py 文件一起使用,但也可以完全替代 setup.py 文件,特别是在使用现代的构建工具(如 setuptoolswheel)时。setup.cfg 文件的格式基于 INI 文件格式,易于阅读和维护。

0.2 setup.cfg 的作用

setup.cfg 文件的主要作用是:

  1. 定义包的元数据:如包名、版本、作者、描述等。
  2. 指定构建选项:如依赖项、入口点、包数据等。
  3. 配置构建工具:如 setuptoolswheel 的行为。
0.3 ironic的setup.cfg的语法解释
# [metadata] 节定义了项目的元数据,这些信息将显示在 PyPI 上,也可能被其他工具使用
[metadata]
name = ironic  # 项目名称
summary = OpenStack Bare Metal Provisioning  # 项目简短描述
description_file =  # 包含项目详细描述的文件
    README.rst
author = OpenStack  # 项目作者
author_email = openstack-discuss@lists.openstack.org  # 作者邮箱
home_page = https://docs.openstack.org/ironic/latest/   # 项目主页 URL
python_requires = >=3.9  # 指定支持的 Python 版本
classifier =  # 项目的分类信息,用于在 PyPI 上分类项目
    Environment :: OpenStack
    Intended Audience :: Information Technology
    Intended Audience :: System Administrators
    License :: OSI Approved :: Apache Software License
    Operating System :: POSIX :: Linux
    Programming Language :: Python
    Programming Language :: Python :: 3 :: Only
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3.9
    Programming Language :: Python :: 3.10
    Programming Language :: Python :: 3.11
    Programming Language :: Python :: 3.12

# [files] 节定义了项目中包含的文件和目录
[files]
# TODO(dtantsur): remove rootwrap files after the packagers drop them.
data_files =  # 定义了要包含在分发包中的数据文件
    etc/ironic =
        etc/ironic/rootwrap.conf
    etc/ironic/rootwrap.d = etc/ironic/rootwrap.d/*
    share/ironic/vnc-container = tools/vnc-container/*
packages =  # 定义了要包含的 Python 包
    ironic

# [entry_points] 节定义了项目的入口点,这些入口点可以是命令行脚本、WSGI 应用程序或其他类型的插件
[entry_points]
oslo.config.opts =  # 定义了 oslo.config 的选项
    ironic = ironic.conf.opts:list_opts

oslo.config.opts.defaults =  # 定义了 oslo.config 的默认选项
    ironic = ironic.conf.opts:update_opt_defaults

oslo.policy.enforcer =  # 定义了 oslo.policy 的执行器
    ironic = ironic.common.policy:get_oslo_policy_enforcer

oslo.policy.policies =  # 定义了 oslo.policy 的策略
    ironic.api = ironic.common.policy:list_policies

console_scripts =  # 定义了控制台脚本
    ironic = ironic.command.singleprocess:main
    ironic-api = ironic.command.api:main
    ironic-dbsync = ironic.command.dbsync:main
    ironic-conductor = ironic.command.conductor:main
    ironic-novncproxy = ironic.command.novncproxy:main
    ironic-rootwrap = oslo_rootwrap.cmd:main
    ironic-status = ironic.command.status:main
    ironic-pxe-filter = ironic.command.pxe_filter:main

wsgi_scripts =  # 定义了 WSGI 脚本
    ironic-api-wsgi = ironic.api.wsgi:initialize_wsgi_app

ironic.dhcp =  # 定义了 Ironic 的 DHCP 接口
    dnsmasq = ironic.dhcp.dnsmasq:DnsmasqDHCPApi
    neutron = ironic.dhcp.neutron:NeutronDHCPApi
    none = ironic.dhcp.none:NoneDHCPApi

ironic.hardware.interfaces.bios =  # 定义了 Ironic 的 BIOS 接口
    fake = ironic.drivers.modules.fake:FakeBIOS
    idrac-redfish = ironic.drivers.modules.drac.bios:DracRedfishBIOS

ironic.hardware.interfaces.boot =  # 定义了 Ironic 的启动接口
    fake = ironic.drivers.modules.fake:FakeBoot
    idrac-redfish-virtual-media = ironic.drivers.modules.drac.boot:DracRedfishVirtualMediaBoot
    ilo-pxe = ironic.drivers.modules.ilo.boot:IloPXEBoot

ironic.hardware.interfaces.console =  # 定义了 Ironic 的控制台接口
    fake = ironic.drivers.modules.fake:FakeConsole
    fake-graphical = ironic.drivers.modules.fake:FakeGraphicalConsole

ironic.hardware.interfaces.deploy =  # 定义了 Ironic 的部署接口
    anaconda = ironic.drivers.modules.pxe:PXEAnacondaDeploy
    ansible = ironic.drivers.modules.ansible.deploy:AnsibleDeploy

ironic.hardware.interfaces.firmware =  # 定义了 Ironic 的固件接口
    fake = ironic.drivers.modules.fake:FakeFirmware
    no-firmware = ironic.drivers.modules.noop:NoFirmware
    redfish = ironic.drivers.modules.redfish.firmware:RedfishFirmware

ironic.hardware.interfaces.inspect =  # 定义了 Ironic 的检查接口
    agent = ironic.drivers.modules.inspector:AgentInspect
    fake = ironic.drivers.modules.fake:FakeInspect
    idrac-redfish = ironic.drivers.modules.drac.inspect:DracRedfishInspect

ironic.hardware.interfaces.management =  # 定义了 Ironic 的管理接口
    fake = ironic.drivers.modules.fake:FakeManagement
    idrac-redfish = ironic.drivers.modules.drac.management:DracRedfishManagement
    ilo = ironic.drivers.modules.ilo.management:IloManagement

ironic.hardware.interfaces.network =  # 定义了 Ironic 的网络接口
    flat = ironic.drivers.modules.network.flat:FlatNetwork
    neutron = ironic.drivers.modules.network.neutron:NeutronNetwork
    noop = ironic.drivers.modules.network.noop:NoopNetwork

ironic.hardware.interfaces.power =  # 定义了 Ironic 的电源接口
    agent = ironic.drivers.modules.agent_power:AgentPower
    fake = ironic.drivers.modules.fake:FakePower

ironic.hardware.interfaces.raid =  # 定义了 Ironic 的 RAID 接口
    agent = ironic.drivers.modules.agent:AgentRAID
    fake = ironic.drivers.modules.fake:FakeRAID
    idrac-redfish = ironic.drivers.modules.drac.raid:DracRedfishRAID

ironic.hardware.interfaces.rescue =  # 定义了 Ironic 的救援接口
    agent = ironic.drivers.modules.agent:AgentRescue
    fake = ironic.drivers.modules.fake:FakeRescue
    no-rescue = ironic.drivers.modules.noop:NoRescue

ironic.hardware.interfaces.storage =  # 定义了 Ironic 的存储接口
    fake = ironic.drivers.modules.fake:FakeStorage
    noop = ironic.drivers.modules.storage.noop:NoopStorage

ironic.hardware.interfaces.vendor =  # 定义了 Ironic 的供应商接口
    fake = ironic.drivers.modules.fake:FakeVendorB
    idrac-redfish = ironic.drivers.modules.drac.vendor_passthru:DracRedfishVendorPassthru

ironic.hardware.types =  # 定义了 Ironic 的硬件类型
    fake-hardware = ironic.drivers.fake_hardware:FakeHardware
    idrac = ironic.drivers.drac:IDRACHardware
    ilo = ironic.drivers.ilo:IloHardware

ironic.database.migration_backend =  # 定义了 Ironic 的数据库迁移后端
    sqlalchemy = ironic.db.sqlalchemy.migration

ironic.inspection.hooks =  # 定义了 Ironic 的检查钩子
    ramdisk-error = ironic.drivers.modules.inspector.hooks.ramdisk_error:RamdiskErrorHook
    validate-interfaces = ironic.drivers.modules.inspector.hooks.validate_interfaces:ValidateInterfacesHook
    ports = ironic.drivers.modules.inspector.hooks.ports:PortsHook
    architecture = ironic.drivers.modules.inspector.hooks.architecture:ArchitectureHook

ironic.console.container =  # 定义了 Ironic 的控制台容器
    systemd = ironic.console.container.systemd:SystemdConsoleContainer
    fake = ironic.console.container.fake:FakeConsoleContainer

# [extras] 节定义了项目的额外依赖项,这些依赖项可以根据用户的需求选择性安装
[extras]
guru_meditation_reports =  # guru_meditation_reports 依赖项
  oslo.reports>=1.18.0 # Apache-2.0
i18n =  # i18n 依赖项
  oslo.i18n>=3.20.0 # Apache-2.0
devstack =  # devstack 依赖项
  virtualbmc>=1.4.0 # Apache-2.0

# [codespell] 节定义了代码拼写检查工具 codespell 的配置
[codespell]
quiet-level = 4  # 设置安静级别
ignore-words-list = selectin,exept,taks,ser,wit,cna,myraid,dum,assertin,checkin,authenticatin,burnin  # 定义了要忽略的单词列表
skip = AUTHORS,ChangeLog,*.pyc,*.inv,*.svg,*.png,*.sample,./doc/build/*,./api-ref/build/*,./releasenotes/build/*,./api-ref/build/*,./build/*  # 定义了要跳过的文件和目录

1. 创建项目结构

首先,创建一个基本的项目结构:

my_package/
├── my_package/
│   ├── __init__.py
│   └── example.py
├── setup.cfg
└── README.md

2. 编写 setup.cfg 文件

my_package 目录下创建 setup.cfg 文件,并添加以下内容:

[metadata]
name = my_package
version = 1.0.0
author = Your Name
author_email = your.email@example.com
description = A simple example package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/yourusername/my_package
license = MIT
classifiers =
    Programming Language :: Python :: 3
    License :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
package_dir =
    = .
packages = find:
python_requires = >=3.6
install_requires =
    requests

[options.packages.find]
where = .

[build_sdist]
include = README.md

3. 创建 setup.py 文件

虽然可以完全使用 setup.cfg,但有时仍然需要一个简单的 setup.py 文件来触发构建过程。创建一个空的 setup.py 文件:

from setuptools import setup

setup()

4. 创建 README.md 文件

在项目根目录下创建 README.md 文件,内容如下:

# My Package

A simple example package.

5. 创建 my_package 模块

my_package 目录下创建 src/my_package/__init__.pysrc/my_package/example.py 文件。

src/my_package/__init__.py

from .example import hello

__all__ = ["hello"]

src/my_package/example.py

def hello():
    print("Hello from my_package!")

6. 安装构建工具

确保你已经安装了 setuptoolswheel。如果没有安装,可以使用以下命令安装:

pip install setuptools wheel

7. 构建 wheel 文件

在项目根目录下运行以下命令来构建 wheel 文件:

python setup.py sdist bdist_wheel

这将生成一个 dist 目录,其中包含构建的源分发包(sdist)和 wheel 文件(bdist_wheel)。

8. 安装 wheel 文件

可以使用以下命令安装生成的 wheel 文件:

pip install dist/my_package-1.0.0-py3-none-any.whl

9. 测试安装

安装完成后,可以测试是否可以正常使用生成的包:

python -c "from my_package import hello; hello()"

如果一切正常,会看到输出:

Hello from my_package!

10. 查看wheel的元数据

pip show my_package

$ pip show my_package
Name: my_package
Version: 1.0.0
Summary: A simple example package
Home-page: https://github.com/yourusername/my_package
Author: Your Name
Author-email: your.email@example.com
License: MIT
Location: /home/hanwang/python_practise/make_wheel/myenv/lib/python3.12/site-packages
Requires: requests
Required-by: 

总结

通过使用 setup.cfg 文件,你可以清晰地定义包的元数据和构建选项,使包的构建过程更加简单和可维护。上述步骤展示了如何从头开始创建一个 Python 包,并生成 wheel 文件,以便于分发和安装。

posted @ 2025-06-28 10:38  harrylearn66666  阅读(67)  评论(0)    收藏  举报