【新】使用setuptools打包Python项目
如何使用setuptools打包Python项目
- 如何使用setuptools打包Python项目
- 一、准备
- 二、项目结构
- 三、简单打包
- 3.1 文件内容
- 3.2 打包项目
- 3.3 安装测试
- 四、自定义打包
- 4.1 添加子模块
- 4.2 只生成 whl
- 4.3 包含/排除数据
- 4.4 编译模块
- 4.5 生成可执行命令
pypi 官网给出了4个打包 whl 格式的工具:Hatchling、setuptools、Flit、PDM。
初步了解了一下,还是用 setuptools 。
本文主要内容包括:pyproject.toml 的简单配置、使用 python -m build 打包、使用 cython 编译模块、生成命令等内容。
本文仅为学习经验,深入学习请参考官方文档。
一、准备
安装 setuptools 和 build
pip install --upgrade setuptools # 65.5.0
# 安装 build 以可以运行命令: python -m build
pip install --upgrade build # 0.9.0
二、项目结构
以名为 pypackage 的项目为例(src 结构)
pypackage/
├── LICENSE # LICENSE
├── pyproject.toml # 项目配置信息
├── README.md # 自述文件
├── src # 源码
│ └── pypackage
│ ├── __init__.py
│ └── __main.py
└── tests # 相关的测试└── test_main.py
还有另一种结构(flat 结构)
pypackage/
├── LICENSE # LICENSE
├── pyproject.toml # 项目配置信息
├── README.md # 自述文件
│── pypackage # 名字为项目名
│ ├── __init__.py
│ └── __main.py
└── tests # 相关的测试└── test_main.py
setuptools 具有自动检测项目代码目录的功能。另外需要说明的是,使用 src-layout 的形式时,会添加 src 下的所有目录,建议 src 下只保留一个与项目名同名的目录
三、简单打包
3.1 文件内容
src/pypackage/__init__.py
from .__main import say_hello
src/pypackage/__main.py
def say_hello(name: str):__private_say(name)def __private_say(name: str):print(f"private say: Hello, {name}!")
tests/test_main.py
TEST_RELEASE = True
if not TEST_RELEASE:import sysimport pathlibroot_dir = pathlib.Path(__file__).absolute().parent.parentsys.path.insert(0, str(root_dir.joinpath("src")))# using pytest
def test_hello():import pypackage pypackage.say_hello("yluuu")
pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"[project]
name = "pypackage"
version = "0.0.1"
dependencies = ["requests","rtoml; python_version<'3.8'",
]
3.2 打包项目
默认情况会根据依赖包创建一个隔离的虚拟环境来打包,但我是离线环境,所以不能用这种方式,需要添加 --no-isolation
选项
python -m build --no-isolation
打包如果成功会提示:Successfully built pypackage-0.0.1.tar.gz and pypackage-0.0.1-py3-none-any.whl
,共生成了两个文件
3.3 安装测试
使用 pip 安装 whl 文件,查看安装目录 ~/miniconda3/lib/python3.7/site-packages/pypackage
-rw-rw-r-- 1 yl yl 30 10月 31 08:19 __init__.py
-rw-rw-r-- 1 yl yl 124 10月 31 08:19 __main.py
drwxrwxr-x 2 yl yl 4.0K 10月 31 08:19 __pycache__
在项目根目录下直接运行 pytest
命令,测试没有问题
~/test/pypackage ----------------- base py | yl@jisuan01 | 08:30:28
> pytest
======================== test session starts =========================
platform linux -- Python 3.7.13, pytest-7.2.0, pluggy-1.0.0
rootdir: /home/yl/test/pypackage
collected 1 item tests/test_main.py . [100%]========================= 1 passed in 0.01s ==========================
四、自定义打包
4.1 添加子模块
setuptools 有自动发现的功能:对于常用的两种项目形式(src-layout、flat-layout),setuptools 可以自动扫描并发现代码目录。
添加文件 src/pypackage/lib1/mod1.py
def func1():return 1
添加文件 src/pypackage/lib2/mod2.py
def func2():return 2
src 及 项目下的模块均可以自动被添加
adding 'pypackage/__init__.py'
adding 'pypackage/__main.py'
adding 'pypackage/lib1/mod1.py' # 自动添加了
adding 'pypackage/lib2/mod2.py' # 自动添加了
adding 'pypackage-0.0.1.dist-info/LICENSE'
adding 'pypackage-0.0.1.dist-info/METADATA'
adding 'pypackage-0.0.1.dist-info/WHEEL'
adding 'pypackage-0.0.1.dist-info/top_level.txt'
adding 'pypackage-0.0.1.dist-info/RECORD'
更多请参考: https://setuptools.pypa.io/en/latest/userguide/package_discovery.html
4.2 只生成 whl
添加选项 --wheel
即可
python -m build --no-isolation --wheel
4.3 包含/排除数据
如 添加 keep.parquet 排除 exclude.txt
pypackage/
├── ...
│── src
│ └── pypackage
│ ├── __init__.py
│ ├── __main.py
│ └── data
│ ├── keep.parquet
│ └── exclude.txt
└── ...
在 pyproject.toml
添加
[tool.setuptools]
include-package-data = true[tool.setuptools.package-data]
pypackage = ["data/*.parquet"][tool.setuptools.exclude-package-data]
pypackage = ["data/*.txt"]
其实 include-package-data
默认就是 true 的
打包记录
adding 'pypackage/__init__.py'
adding 'pypackage/__main.py'
adding 'pypackage/data/keep.parquet' # 这里
adding 'pypackage/lib1/mod1.py'
adding 'pypackage/lib2/mod2.py'
adding 'pypackage-0.0.1.dist-info/LICENSE'
adding 'pypackage-0.0.1.dist-info/METADATA'
adding 'pypackage-0.0.1.dist-info/WHEEL'
adding 'pypackage-0.0.1.dist-info/top_level.txt'
adding 'pypackage-0.0.1.dist-info/RECORD'
更多请参考: https://setuptools.pypa.io/en/latest/userguide/datafiles.html
4.4 编译模块
使用 cython
pip install cython --upgrade
创建 setup.py
# 方式一:按 setuptools 文档,使用 Extension 类,使用 cython 编译时无法设置 language_level TODO 待解决
# from setuptools import setup, Extension# setup(
# ext_modules=[
# Extension(
# name="pypackage.lib1.mod1",
# sources=["src/pypackage/lib1/mod1.pyx"],
# )
# ]
# )# 方式二:直接调用 cython,可以设置 language_level
# 备注: 子模块尽量添加 __init__.py 以确保编译后的库文件可以正常打包到子模块中。
from setuptools import setup
from Cython.Build import cythonizesetup(ext_modules=cythonize(module_list=["src/pypackage/lib1/mod1.pyx"], language_level=3)
)
另外在 pyproject.toml
中排除 c 文件打包
[tool.setuptools.exclude-package-data]
pypackage = ["info/*.txt"]
"pypackage.lib1" = ["*.c"]
将 src/pypackage/lib1/mod1.py
重命名为 src/pypackage/lib1/mod1.pyx
,并在 src/pypackage/lib1
下添加 __init__.py
文件
然后使用 python -m build
时会自动调用 setup.py
生成库文件并打包
单独编译模块时运行 python setup.py build_ext
备注:测试过程中的坑,都在上面的注释里了
adding 'pypackage/__init__.py'
adding 'pypackage/__main.py'
adding 'pypackage/info/keep.parquet'
adding 'pypackage/lib1/__init__.py'
adding 'pypackage/lib1/mod1.cpython-37m-x86_64-linux-gnu.so'
adding 'pypackage/lib2/mod2.py'
adding 'pypackage-0.0.1.dist-info/LICENSE'
adding 'pypackage-0.0.1.dist-info/METADATA'
adding 'pypackage-0.0.1.dist-info/WHEEL'
adding 'pypackage-0.0.1.dist-info/top_level.txt'
adding 'pypackage-0.0.1.dist-info/RECORD'
4.5 生成可执行命令
在 __main.py
中添加以下内容作为可执行命令的入口
def hello():__private_say("pypackage")
然后在 pypackage.toml
中添加名为 pypackage-hello
的命令(在命令行中可直接运行 pypackage-hello
)
[project.scripts]
pypackage-hello = "pypackage.__main:hello"
完成。重新打包安装后效果如下:
> pypackage-hello
private say: Hello, pypackage!
【新】使用setuptools打包Python项目相关推荐
- pyinstaller精简打包python项目完整流程,含常见问题解决方案
最近写了一个python爬虫小项目,想打包成一个exe文件,放在其他电脑上使用.但是没想到一个20B的py文件打包过程却十分艰辛.先后经历了打包失败无法运行,打包成功但是运行十分缓慢,打包了一大堆不需 ...
- python setup.py build_打包Python项目为rpm时遇到python setup.py build报错的问题
问题描述 使用rpmbuild打包python项目,执行报错 rpmbuild -bb autoinstall.spec hrwxr-xr-x XXX/XXX 0 2018-12-19 13: ...
- 使用pyinstaller打包python_使用pyinstaller打包Python项目,python
00 前言 上一篇文章写的是使用百度aip实现一个图片转文字的小工具( https://blog.csdn.net/George_Clancy/article/details/105551872 ), ...
- 2021-01-22 使用 Docker 打包 Python 项目
使用 Docker 打包 Python 项目 1. 获取 Python 的镜像文件 项目的封装可以建立在已有镜像的基础上,在 Ubuntu 中可通过 docker pull python:3.6.8- ...
- docker打包Python项目
docker打包Python项目 Step1: 配置运行环境文档 项目结构如下 docker_test ├── Dockerfile ├── (myapps) │ └── BPNN.py └── re ...
- Python编程:twine模块打包python项目上传pypi
注册账号(重要) https://pypi.org 可以配置到$HOME/.pypirc文件中,就不用多次输入了 [pypi] username = <username> password ...
- 船新的100个Python项目,看了再学毕竟快乐总是一闪而过
Github上面有很多有趣的python项目,包括软件.库.教程.资源等.这次收集了其中比较受欢迎的100个,供大家参考.(内容比较多,建议收藏了再看!) 资料来源:https://github.co ...
- python程序打包多个py文件_不使用setup.py,打包 Python 项目
我编写了许多开源项目,并允许其他人通过PyPI访问这些项目.为此,我需要从这些项目构建一个源代码分发版(sdist)和一个可选的wheel包,并将二者上传到PyPI.最后,这个sdist和wheel包 ...
- 新浪云python示例_新浪SAE部署python项目
SAE实际上就是个多节点的虚拟主机,跟云主机差不多,只不过SAE的节点比一般的云主机要多,把网站程序布署在SAE上比自己用独立的服务器稳定性和性能要高很多.将自己用python开发的博客项目放在SAE ...
最新文章
- 记一次大规模数据迁移和加密
- React基础——快速搭建开发环境
- Jmeter工具笔记-Jmeter+influxdb+grafanas设置性能监控过程
- 《机器学习》 —— 第一章:绪论 学习笔记
- 前端学习(2159):vuecli脚手架的配置和安装
- Cloud一分钟 | 马云发表致股东的公开信;5G算什么?中国已着手研究6G相关工作...
- .net mvc ajax 用html()怎么出来正个页面呀,如何使用jquery或ajax为MVC项目更新c#/ asp.net中的razor部分视图...
- 发条js调试工具_【转载】移动端js调试工具:eruda
- Mysql密码忘记怎么办?重置密码完整教程
- 提取文本手机号 易语言代码
- 动态添加SqlParameter
- Excel绘制折线图--更新中。。。
- 没有更改计算机日期权限,修改电脑时间_修改电脑时间没有权限
- 盘点那些年,被Oracle收购的公司
- 简答实现登录注册(需要导入JQ库)
- C++在终端、文件中就地覆盖输出的方法
- vc++ 编程 经典电子书
- crm day03 创建市场活动
- python valueerror object2_Python使用json.loads 报错 ValueError: No JSON object could be decoded的解决方法...
- 超宽带定位中的TOA/TDOA两种最常用算法介绍
热门文章
- Apache年度报告出炉,大数据项目依然最活跃
- 2022世界传感器大会 | 龙芯中科发布龙芯2K0500多功能SoC芯片及解决方案
- 架构师之路046 服务端开发的总结
- 惠普HP CM1312nfi 彩色激光打印机如何添加网络打印机
- 解决办法:360压缩解压出现空白文件创建失败,但压缩包文件无损坏显示有十几个文件
- 【java并发编程】无锁并发框架disruptor
- ghost后分区丢失如何恢复数据-分区表医生!
- 2022年团体程序设计天梯赛-总决赛
- oracle分页改写为mysql_mysql和oracle分页
- MediaPlayer代码分析(1)-初始化和设置数据的过程