Python打包之setuptools

参考链接 1

参考链接 2

参考链接 3

一、setuptools 介绍

Setuptools 是 Python Distutils 的加强版,使开发者构建和发布 Python 包更加容易,特别是当包依赖于其他包时。用 setuptools 构建和发布的包与用 Distutils 发布的包是类似的。包的使用者无需安装 setuptools 就可以使用该包。如果用户是从源码包开始构建,并且没有安装过 setuptools 的话,则只要在你的 setup 脚本中包含一个 bootstrap 模块(ez_setup),用户构建时就会自动下载并安装 setuptools 了。

功能亮点:

  • 利用 EasyInstall 自动查找、下载、安装、升级依赖包
  • 创建 Python Eggs
  • 包含包目录内的数据文件
  • 自动包含包目录内的所有的包,而不用在 setup.py 中列举
  • 自动包含包内和发布有关的所有相关文件,而不用创建一个 MANIFEST.in 文件
  • 自动生成经过包装的脚本或 Windows 执行文件
  • 支持 Pyrex,即在可以 setup.py 中列出.pyx 文件,而最终用户无须安装 Pyrex
  • 支持上传到 PyPI
  • 可以部署开发模式,使项目在 sys.path 中
  • 用新命令或 setup() 参数扩展 distutils,为多个项目发布 / 重用扩展
  • 在项目 setup() 中简单声明 entry points,创建可以自动发现扩展的应用和框架

 

二、简单的例子

python 中安装包的方式有很多种:

  1. 源码包:python setup.py install
  2. 在线安装:pip install 包名 / easy_install 包名

pip install 的东西从哪里来的?

从 PyPI (Python Package Index)来的,官网是:  https://pypi.python.org/pypi

执行 pip install terminaltranslator 命令的时候,它就会去从官方网站搜 terminaltranslator,搜到了就下载压缩包并解压安装,如果没有搜索到就会报错。

1、源码包安装

源码包安装就是你在本地编写好了一个模块,自己安装在本地使用,别人 (即使是你自己) 都不能 pip install xxx 下载你的模块

1. 准备工作

# 1. 首先创建我们需要的目录结构和文件 (自行创建)
# 当前测试的目录是: /tmp/demo
`-- demo |-- helloapp | |-- hello.py | `-- __init__.py |-- __init__.py |-- myapp | |-- __init__.py | `-- myapp.py `-- setup.py

# 2. 编辑 setup.py
from setuptools import setup, find_packages

setup(
name="demo",
version
="1.0",
author
="zbj",
author_email
="22@qq.com",
packages
=find_packages(),
)

# 3. 编辑 hello.py
def hello_func():
print("HelloWorld")

# 4. 编辑 myapp.py
def myapp_func():
print("嘿嘿嘿")

 

2. 源码安装

# 进入 setup.py 所在的那层目录
cd /tmp/demo

# 检查 setup.py 是否有错误 (warning 不是错误)
python setup.py check

# 安装
python setup.py install

 

3. 结果

打包之后多出两个文件夹,分别是 demo.egg-info 和 dist。demo.egg-info 是必要的安装信息,

而 dist 中的压缩包就是安装包,此时默认的 egg 包,egg 包就是 zip 包,如果需要使用 egg 包,name 将 egg 后缀改成 zip 解压即可

 

4. 测试

测试的时候需要注意导包路径和当前所在路径
目前所在路径是: /tmp/demo
直接进入 python 解释器: python3(我自己安装的 python3 版本)

 

 

 

5.setuptools 更多参数用法 

https://setuptools.readthedocs.io/en/latest/setuptools.html

 

2、打包上传到 pypi

官网连接

2-1、配置文件和打包

1. 创建文件的目录结构

hello/
|-- hello
|   |-- hello.py
|   `-- __init__.py
|-- LICENSE
|-- README.md
`-- setup.py

 

2. setup.py

from setuptools import setup, find_packages

setup(
name="hello",
version
='1.0',
description
="Test Hello",
url
="None",
author
="zbj",
author_email
="22@qq.com",
license
="MIT",
packages
=find_packages()
)

 

3. LICENSE

LICENSE 代表许可证

官网

Copyright (c) 2018 The Python Packaging Authority

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software
and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell
copies of the Software,
and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

 

4. setuptools 和 wheel

首先需要保证你有最新版的setuptools 和wheel

python -m pip install --user --upgrade setuptools wheel

Tip:如果出现问题了可以查看官网的解决方案:https://packaging.python.org/tutorials/installing-packages/

 

5. 打包模块

# 进入到 setup.py 同级的目录下
python setup.py sdist bdist_wheel

打包之后多出两个文件夹,分别是 hello.egg-info 和 dist。hello.egg-info 是必要的安装信息,而 dist 中的压缩包就是安装包

dist 中包含两个文件:

dist/
|-- hello-1.0-py3-none-any.whl
`-- hello-1.0.tar.gz

 

6. 打包方式介绍

有了上面的 setup.py 文件,我们就可以打出各种安装包,主要分为两类:sdist 和 bdist。

Source distribution

使用 sdist 可以打包成 source distribution,支持的压缩格式有:

FormatDescriptionNotes
zip zip file (.zip) Windows 默认
gztar gzip’ed tar file (.tar.gz) Unix 默认
bztar bzip2’ed tar file (.tar.bz2)  
xztar xz’ed tar file (.tar.xz)  
ztar compressed tar file (.tar.Z)  
tar tar file (.tar)  

使用方式为:

$ python setup.py sdist --formats=gztar,zip

现在目录下多出 dist 和 *.egg-info 目录,dist 内保存了我们打好的包,上面命令使用 --formats 指定了打出 .tar.gz.zip 包,如果不指定则如上表根据具体平台默认格式打包。

包的名称为 setup.py 中定义的 name, version以及指定的包格式,格式如:firstApp-0.0.1.tar.gz。

Built distribution

使用 bdist 可以打出 built distribution,和源码包相比,由于预先构建好,所以安装更快:

FormatDescriptionNotes
gztar gzipped tar file (.tar.gz) Unix 默认
bztar bzipped tar file (.tar.bz2)  
xztar xzipped tar file (.tar.xz)  
ztar compressed tar file (.tar.Z)  
tar tar file (.tar)  
zip zip file (.zip) Windows 默认
rpm RPM  
pkgtool Solaris pkgtool  
sdux HP-UX swinstall  
wininst self-extracting ZIP file for Windows  
msi Microsoft Installer.  

使用上,和 sdist 一样,可以使用 --formats 指定包格式。如:

$ python setup.py bdist --formats=rpm

同时为了简化操作,setuptools 提供了如下命令:

CommandFormatsNotes
bdist_dumb tar, gztar, bztar, xztar, ztar, zip Windows 默认 zip, Unix 默认 gztar
bdist_rpm rpm, srpm  
bdist_wininst wininst  
bdist_msi msi  

所以上面打 rpm 包可以使用:

$ python setup.py bdist_rpm

 

2-2、上传到 Pypi

此时前置打包的步骤已经完成,可以开始进行上传。

1. 利用twine将包上传上去,首先安装 twine

pip install twine

 

2. 注册 PyPI 账号

登录 https://pypi.python.org/pypi,注册账号

 

3. 上传

# 使用 upload
$ twine upload dist/*
输入 username 和 password 即上传至 PyPI。

# 如果不想每次输入账号密码,可以在家目录下创建 .pypirc 文件,内容如下:

[distutils]
index
-servers =
pypi
pypitest

[pypi]
username:
password:

[pypitest]
repository: https://test.pypi.org/legacy/
username:
password:

 

4. 检验
这时候就可以,下载包,然后运行里面方法了

pip install hello
在本地测试的时候可以直接安装打包好的 dist 下的包:
pip install xxx.tag.gz
测试功能正常后再上传到 pypi
提示

 

5. 更新版本
更新版本也很简单,只需要修改 setup.py 下的 version
然后重新生成档案,上传

python setup.py sdist bdist_wheel
twine upload dist/hello-0.0.2*

 

6. 更新本地 moudle 版本

pip install --upgrade hello

或者是先卸载,再安装
# 卸载 hello
pip uninstall hello
# 安装 hello
pip install hello

 

 

三、setuptools 的进阶使用

上面使用 setuptools 时只是简单的用一个配置文件 setup.py 就完成了打包信息填写。在真实的开发环境中,往往是多个文件配合。以 openstack 的打包为例。openstack 中引入了 Pbr 的管理工具。

pbr 是 setuptools 的辅助工具,最初为 openstack 开发,基于 d2to1。Pbr 会读取和过滤 setup.cfg 中的内容,然后将解析后的数据提供给 setup.py 作为参数。
setup.cfg 提供 setup.py 的默认参数,同时易于修改。Setup.py 先解析 setup.cfg 文件,然后执行相关命令。包括以下功能:

1、从 git 中获取 Version,AUTHORS 和 ChangeLog 信息

2、SphinxAutodoc。pbr 会扫描 project,找到所有模块,生成 stubfiles

3、Requirements。读取 requirements.txt 文件,生成 setup 函数需要依赖包

4、long_description。从 README.rst、README.txt 或者 READMEfile 中生成 long_description 参数

 

Pbr 的文件很简单,如下。配置之后会自动寻找目录下的 setup.cfg 文件,解析文件参数给 setup.py 使用。

https://docs.openstack.org/pbr/latest/user/using.html

setup.py

from setuptools import setup

setuptools.setup(

setup_requires=['pbr'],

pbr=True)

 

setup.cfg

[metadata]
name = my_package
version = attr: src.VERSION
description = My package description
long_description = file: README.rst, CHANGELOG.rst, LICENSE.rst
keywords = one, two
license = BSD 3-Clause License
classifiers =
    Framework :: Django
    License :: OSI Approved :: BSD License
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3.5

[files]
packages =
project_name
data_files
=
etc
/pbr = etc/pbr/*

[global]
setup
-hooks =
pbr.hooks.setup_hook

[entry_points]
console_scripts =
project_name
= project.cmd.mycmd:main

[options]
zip_safe = False
include_package_data
= True
packages
= find:
scripts
=
bin
/first.py
bin
/second.py
install_requires
=
requests
importlib; python_version
== "2.7"

[options.package_data]
* = *.txt, *.rst
hello
= *.msg

[options.extras_require]
pdf = ReportLab>=1.2; RXP
rest
= docutils>=0.3; pack ==1.1, ==1.3

[options.packages.find]
exclude =
src.subpackage1
src.subpackage2

[options.data_files]
/etc/my_package =
site.d
/00_default.conf
host.d
/00_default.conf
data
= data/img/logo.png, data/svg/icon.svg