Python程序包的构建和发布过程示例详解


Posted in Python onJune 09, 2019

关于我

编程界的一名小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 联系:hylinux1024@gmail.com

当我们开发了一个开源项目时,就希望把这个项目打包然后发布到 pypi.org 上,别人就可以通过 pip install 的命令进行安装。本文的教程来自于 Python 官方文档 , 如有不正确的地方欢迎评论拍砖。

0x00 创建项目

本文使用到的项目目录为

➜ packaging-tutorial
.
└── bestpkg
  └── __init__.py

接下来的所有操作都是在 packing_tutorial 这个目录下进行的。首先把 bestpkg 这个目录下的 __init__.py 添加以下内容

info='packaging demo'

这个信息主要用于打包成功后安装测试用的。

0x01 项目结构

一个待发布的项目还需要有以下这些文件: setup.py 、 LICENSE 和 README.md

➜ packaging-tutorial
.
├── LICENSE
├── README.md
├── bestpkg
│  └── __init__.py
└── setup.py

0x02 setup.py

setup.py 文件是给 setuptools 工具的使用脚本,告诉 setuptools 如何构建我们的项目。打开编辑器,编辑 setup.py 文件,输入以下内容

import setuptools

# 读取项目的readme介绍
with open("README.md", "r") as fh:
  long_description = fh.read()

setuptools.setup(
  name="bestpkg",# 项目名称,保证它的唯一性,不要跟已存在的包名冲突即可
  version="0.0.1",
  author="hylinux1024", # 项目作者
  author_email="hylinux1024@gmail.com",
  description="一个牛逼的程序", # 项目的一句话描述
  long_description=long_description,
  long_description_content_type="text/markdown",
  url="https://github.com/hylinux1024/niubiproject",# 项目地址
  packages=setuptools.find_packages(),
  classifiers=[
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
  ],
)
  • name 
  • 项目名称,保证它的唯一性,不要跟已存在的包名冲突即可,否则会发布失败
  • version 
  • 版本号
  • author 
  • 作者
  • author_email 
  • 作者邮箱
  • description 
  • 一句话描述项目
  • long_description 
  • 项目详细说明,一般直接读取README.md的内容
  • url 
  • 项目的链接地址
  • packages 
  • 列出当前项目的包,一般直接使用 find_packages() 即可
  • classifiers 
  • 这里指定 Python 的兼容版本是 Python3 ,也指定了项目使用的开源协议。

0x03 README.md

给项目添加详细的 README

# Example Package

This is a simple example package. You can use
[Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
to write your content.

0x04 LICENSE

要发布包到 pypi 上,选择一个合适的开源协议是非常重要的。如果不知道怎么选可以到choosealicense.com/这里看看。

0x05 项目打包

项目需要打包后才能发布,要打包项目需先安装最新版本的 setuptools 和 wheel

➜ python3 -m pip install --user --upgrade setuptools wheel

然后使用以下命令进行打包

➜ python3 setup.py sdist bdist_wheel

当看到以下信息,说明已经打包成功

...
...
...
adding license file "LICENSE" (matched pattern "LICEN[CS]E*")
creating build/bdist.macosx-10.14-x86_64/wheel/bestpkg-0.0.1.dist-info/WHEEL
creating 'dist/bestpkg-0.0.1-py3-none-any.whl' and adding 'build/bdist.macosx-10.14-x86_64/wheel' to it
adding 'bestpkg/__init__.py'
adding 'bestpkg-0.0.1.dist-info/LICENSE'
adding 'bestpkg-0.0.1.dist-info/METADATA'
adding 'bestpkg-0.0.1.dist-info/WHEEL'
adding 'bestpkg-0.0.1.dist-info/top_level.txt'
adding 'bestpkg-0.0.1.dist-info/RECORD'
removing build/bdist.macosx-10.14-x86_64/wheel

在项目目录下会生成一个 dist 和 build 文件夹

➜ packaging-tutorial tree
.
├── LICENSE
├── README.md
├── bestpkg
│  └── __init__.py
├── bestpkg.egg-info
│  ├── PKG-INFO
│  ├── SOURCES.txt
│  ├── dependency_links.txt
│  └── top_level.txt
├── build
│  ├── bdist.macosx-10.14-x86_64
│  ├── bdist.macosx-10.9-x86_64
│  └── lib
│    └── bestpkg
│      └── __init__.py
├── dist
│  ├── bestpkg-0.0.1-py3-none-any.whl
│  └── bestpkg-0.0.1.tar.gz
└── setup.py

8 directories, 11 files

在 dist 文件中有两个文件

dist
  ├── bestpkg-0.0.1-py3-none-any.whl
  └── bestpkg-0.0.1.tar.gz

tar.gz 文件是源码文件压缩包,而 .whl 就是打包后的文件。最新的 pip 命令会安装这个 .whl 文件。

0x06 上传

现在就可以上传到 Python 索引库了。我们使用 Test PyPI ,这个是测试用的 Pypi ,本例子也是使用 Test Pypi 。

首先要到 test.pypi.org/account/reg… 注册账号。本例中我注册的账号为: hylinux1024 。

然后使用 twine 工具来上传我们的包。使用以下命令进行安装:

➜ python3 -m pip install --user --upgrade twine

使用以下命令上传 dist 目录下的文件

➜ python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*

这个命令会提示输入刚在 test.pypi.org 上注册账号密码,并出现类似以下信息后说明已经上传成功。

Enter your username: hylinux1024
Enter your password:
Uploading distributions to https://test.pypi.org/legacy/
Uploading bestpkg-0.0.1-py3-none-any.whl
100%|??????????????????????????????????????| 4.57k/4.57k [00:00<00:00, 8.01kB/s]
Uploading bestpkg-0.0.1.tar.gz
100%|??????????????????????????????????????| 4.18k/4.18k [00:01<00:00, 3.23kB/s]

然后打开 test.pypi.org/project/bes… 这个地址就可以看到我们发布的包。

0x07 安装

发布成功之后就可以使用 pip 来安装来。我们在虚拟环境中安装,关于虚拟环境可以看我前一篇文章。

这里就使用 pipenv ,这里我直接进入到我昨天创建的那个项目中,也为了更好演示安装结果。

➜ pip install --index-url https://test.pypi.org/simple/ --no-deps bestpkg

在这里我使用 --index-url 参数是为了指定从 test.pypi.org 中安装,而不是正式包索引库中查找要安装的包。还有使用了 --no-deps 参数是因为本例中没有使用到其它的依赖库。

在终端会看到以下类似信息,说明安装成功

Looking in indexes: https://test.pypi.org/simple/
Collecting bestpkg
 Downloading https://test-files.pythonhosted.org/packages/5a/fc/c109b3872b6c06e7368c30b6e52501113846f90ca716a434766151093173/bestpkg-0.0.1-py3-none-any.whl
Installing collected packages: bestpkg
Successfully installed bestpkg-0.0.1

进入交互界面

(pipenvdemo) ➜ pipenvdemo python
>>> import bestpkg
>>> bestpkg.info
'packaging demo'

info 变量就是在 __init__.py 文件中定义的变量。自此我们的包发布、安装使用流程就走完了。

要在正式的 Python 索引库中发布,只需要到pypi.org/注册账号,并上传就可以了。

0x08 总结一下

通过一个简单的例子展示 Python 通过 setuptools 工具进行打包,然后上传到 test.pypi.org 的流程。如果要上传到正式的 pypi.org 上,只需要注册一个正式的账号。一旦发布成功就可以使用 pip install [your-package] 的命令进行安装。

总结

以上所述是小编给大家介绍的Python程序包的构建和发布过程示例详解,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Python 相关文章推荐
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 Python
Python 爬虫爬取指定博客的所有文章
Feb 17 Python
TensorFlow saver指定变量的存取
Mar 10 Python
python中文编码与json中文输出问题详解
Aug 24 Python
python之cv2与图像的载入、显示和保存实例
Dec 05 Python
Python实现的对本地host127.0.0.1主机进行扫描端口功能示例
Feb 15 Python
python 执行终端/控制台命令的例子
Jul 12 Python
什么是Python变量作用域
Jun 03 Python
Python 列表中的修改、添加和删除元素的实现
Jun 11 Python
Android Q之气泡弹窗的实现示例
Jun 23 Python
Python通过队列来实现进程间通信的示例
Oct 14 Python
Python经典五人分鱼实例讲解
Jan 04 Python
Python面向对象之继承和多态用法分析
Jun 08 #Python
Python基本数据结构之字典类型dict用法分析
Jun 08 #Python
Python学习笔记基本数据结构之序列类型list tuple range用法分析
Jun 08 #Python
Python面向对象之类的封装操作示例
Jun 08 #Python
Python面向对象之类和实例用法分析
Jun 08 #Python
Python学习笔记之自定义函数用法详解
Jun 08 #Python
Python3基础教程之递归函数简单示例
Jun 07 #Python
You might like
如何使用PHP往windows中添加用户
2006/12/06 PHP
destoon整合UCenter图文教程
2014/06/21 PHP
PHP7正式版测试,性能惊艳!
2015/12/08 PHP
PHP图片加水印实现方法
2016/05/06 PHP
PHP字典树(Trie树)定义与实现方法示例
2017/10/09 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
Javascript 自适应高度的Tab选项卡
2011/04/05 Javascript
javascript通过className来获取元素的简单示例代码
2014/01/10 Javascript
JQuery调用WebServices的方法和4个实例
2014/05/06 Javascript
无限树Jquery插件zTree的常用功能特性总结
2014/09/11 Javascript
相册展示PhotoSwipe.js插件实现
2016/08/25 Javascript
详解JavaScript的内置对象
2016/12/07 Javascript
js实现功能比较全面的全选和多选
2017/03/02 Javascript
Angular动态添加、删除输入框并计算值实例代码
2017/03/29 Javascript
webpack独立打包和缓存处理详解
2017/04/03 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
vue的toast弹窗组件实例详解
2018/05/14 Javascript
npm 语义版本控制详解
2019/09/10 Javascript
ES6函数实现排它两种写法解析
2020/05/13 Javascript
three.js 如何制作魔方
2020/07/31 Javascript
js+canvas绘制图形验证码
2020/09/21 Javascript
vue el-upload上传文件的示例代码
2020/12/21 Vue.js
python微信跳一跳系列之自动计算跳一跳距离
2018/02/26 Python
python爬取哈尔滨天气信息
2018/07/14 Python
python多任务之协程的使用详解
2019/08/26 Python
python实现密码验证合格程序的思路详解
2020/06/01 Python
日本著名的平价时尚女性购物网站:Fifth
2016/08/24 全球购物
会计系个人求职信范文分享
2013/12/20 职场文书
服装厂厂长岗位职责
2013/12/27 职场文书
家长对老师的感言
2014/03/11 职场文书
新教师培训方案
2014/06/08 职场文书
2016年优秀团员事迹材料
2016/02/25 职场文书
SpringBoot项目中控制台日志的保存配置操作
2021/06/18 Java/Android
Go语言实现一个简单的并发聊天室的项目实战
2022/03/18 Golang
python获取带有返回值的多线程
2022/05/02 Python