如何构建含自动生成Python文件的Python包?
Python包自动编译YAML并打包的解决方案
核心逻辑
通过扩展setuptools的构建命令,在包构建或源码安装阶段自动执行YAML到Python的编译步骤,将生成文件纳入最终包中,同时确保编译工具仅作为构建依赖,不影响用户运行环境。
步骤1:更新pyproject.toml配置
首先补充构建依赖,把编译需要的kaitaistruct加入构建系统依赖列表:
[build-system] requires = ["setuptools", "kaitaistruct"] build-backend = "setuptools.build_meta" [project] name = "<package>" version = "xyz" description = "<description>" authors = [ <authors> ] dependencies = [ "kaitaistruct", ] # 可选:指定要包含的生成文件,确保打包时不会遗漏 [tool.setuptools.package-data] "<project>" = ["generated/*.py"]
步骤2:编写自定义构建脚本(setup.py)
创建setup.py,重写setuptools的build_py命令,让它在复制Python文件前先完成YAML编译:
from setuptools import setup from setuptools.command.build_py import build_py import os from kaitaistruct import compile class CustomBuildPy(build_py): def run(self): # 定义路径 pkg_root = self.package_dir["<project>"] specs_dir = os.path.join(pkg_root, "specs") generated_dir = os.path.join(pkg_root, "generated") # 创建生成目录(不存在则自动创建) os.makedirs(generated_dir, exist_ok=True) # 遍历并编译所有.ksc文件 for fname in os.listdir(specs_dir): if fname.endswith(".ksc"): spec_path = os.path.join(specs_dir, fname) output_fname = f"{os.path.splitext(fname)[0]}.py" output_path = os.path.join(generated_dir, output_fname) compile(spec_path, output_path) # 执行原build_py的文件复制逻辑 super().run() setup( cmdclass={ 'build_py': CustomBuildPy, } )
步骤3:支持可编辑模式(可选)
如果需要pip install -e .的可编辑安装也能自动编译,扩展develop命令:
# 在setup.py中添加以下内容 from setuptools.command.develop import develop class CustomDevelop(develop): def run(self): # 编译逻辑和之前一致 specs_dir = os.path.join("<project>", "specs") generated_dir = os.path.join("<project>", "generated") os.makedirs(generated_dir, exist_ok=True) for fname in os.listdir(specs_dir): if fname.endswith(".ksc"): spec_path = os.path.join(specs_dir, fname) output_fname = f"{os.path.splitext(fname)[0]}.py" output_path = os.path.join(generated_dir, output_fname) compile(spec_path, output_path) super().run() # 更新setup的cmdclass setup( cmdclass={ 'build_py': CustomBuildPy, 'develop': CustomDevelop, } )
同时在pyproject.toml中添加文件监听,方便修改YAML后重新编译:
[tool.setuptools.editable_watch_files] "<project>/specs/*.ksc" = ["<project>/generated/"]
各场景验证
- PyPI安装:上传到PyPI的wheel已包含所有生成文件,用户直接安装即可使用,无需编译。
- 本地构建wheel:执行
python -m build . --wheel时,会自动编译YAML并将生成文件打包进wheel。 - 源码安装:执行
pip install .时,构建系统会先编译YAML,再完成安装。 - 可编辑模式:执行
pip install -e .时自动编译,修改.ksc文件后重新执行该命令即可更新生成文件。
额外注意事项
- 不要将
generated目录提交到仓库,在.gitignore添加:/<project>/generated/ - 编译工具
kaitaistruct仅作为构建依赖,用户通过PyPI安装wheel时不会安装它;源码安装时会临时安装,安装完成后可手动移除。
内容的提问来源于stack exchange,提问作者e-rk
相关产品推荐
相关产品推荐

