打包发布Python模块的方法详解


Posted in Python onSeptember 18, 2016

前言

昨天把自己的VASP文件处理库进行了打包并上传到PyPI,现在可以直接通过pip和easy_install来安装VASPy啦(同时欢迎使用VASP做计算化学的童鞋们加星和参与进来),

VASPy的GotHub地址:https://github.com/PytLab/VASPy
VASPy的PyPI地址:https://pypi.python.org/pypi/vaspy/

由于自己的记性真是不咋地,怕时间久了就忘了,于是在这里趁热打铁以自己的VASPy程序为例对python的打包和上传进行下总结。

VASPy包文件结构

首先写贴上来VASPy包的整个文件结构, 后面的内容都是以此为例进行说明:

VASPy/
├── LICENSE
├── MANIFEST
├── MANIFEST.in
├── README.rst
├── requirements.txt
├── scripts
│  ├── change_incar_parameters.py
│  ├── create_inputs.py
│  └── ...
├── setup.cfg
├── setup.py
├── tests
│  ├── incar_test.py
│  ├── __init__.py
│  ├── oszicar_test.py
│  ├── outcar_test.py
│  ├── testdata
│  │  ├── CONTCAR
│  │  ├── DOS_SUM
│  │  ├── ELFCAR
│  │  └── ...
│  └── ...
└── vaspy
  ├── __init__.py
  ├── iter.py
  ├── matstudio.py
  └── ...
 
4 directories, 54 files

打包和安装第三方包的工具

这里我们需要借助setuptools和pip等工具进行自己包的打包和发布以及安装,如果需要构建成wheel还需要安装wheel模块。如果python版本>=2.7.9或者>=3.4,setuptools和pip是已经安装好的,可能需要进行更新到最新版本

pip install -U pip setuptools

可以使用包管理工具,例如

yum install pip
sudo apt-get install pip

通过get-pip.py脚本安装,如果检测到没有安装wheel和setuptools也会自动安装

python get-pip.py

具体的工具安装和介绍就不多讲了,可以请参考requirements for installing packages

包中不同文件的作用

setup.py

这个文件是打包整个项目最重要的文件,它里面提供了两个主要的功能:

setup()函数,此函数的参数指定了如何配置自己的项目。
命令行工具,包括打包,测试,发布等。可以通过下面的命令查看;

python setup.py --help-commands

setup.cfg

此文件包含了构建时候的一些默认参数例如构建bdist_wheel的时候的--universal参数

[bdist_wheel]
universal=1

这样每次打包的时候就会默认使用--universal参数了,效果类似:

python setup.py bdist_wheel --universal

README.rst

这个最初我是用markdown写的,打包发布到PyPI之后发现PyPI不支持markdown的渲染,页面上真是一片混乱,于是就用reStrutruedText的语法重新写了一遍。毕竟标记语言语法基本上可以秒上手,实在不行找个模板比葫芦画瓢就行。
reStructureText的语法规则可参考官方文档:Quick reStructuredText

其实还有一种方法就是使用pandoc将markdown转换成rst格式,一种省事的方式就是使用pyandoc模块在发布的时候自动转换。
具体方法可以参考:Use Markdown README's in Python modules

MANIFEST.in

此文件在打包的时候告诉setuptools还需要额外打包那些文件,例如我VASPy中的单元测试的测试数据文件我就使用这个文件将其包含进来。当然README,LICENSE这些也可以通过它来一起打包进来。
下面是我自己的MANIFEST.in的内容:

include README.rst
include requirements.txt
include LICENSE
recursive-include scripts *
recursive-include tests *

具体的语法规则可以参考:The MANIFEST.in template

vaspy/

此文件夹就是vaspy源代码所在的包。

tests/

此文件夹也是一个子包,包含了单元测试脚本,为了能使用python setup.py test进行单元测试,特地添加了__init__.pys使其成为一个包。

setup()的参数

这里只介绍我使用的几个参数,其他参数的具体使用可以参考:https://docs.python.org/3/distutils/setupscript.html

name

versions = "vaspy"

是整个项目的名字,打包后会使用此名字和版本号。

version

from vaspy import __version__
version = __version__

description

是一个简短的对项目的描述,一般一句话就好,会显示在pypi上名字下端。

long_description

是一个长的描述,相当于对项目的一个简洁,如果此字符串是rst格式的,PyPI会自动渲染成HTML显示。这里可以直接读取README.rst中的内容。

url

包的连接,通常为GitHub上的链接或者readthedocs的链接。

packages

需要包含的子包列表,setuptools提供了find_packages()帮助我们在根路径下寻找包,这个函数distutil是没有的。

setup_requires

这个参数定义了VASPy安装和顺利运行所需要的其他依赖项(最基本的),使用pip安装的时候会对这些依赖项进行安装。
关于这个参数与requirements.txt的区别可以参考:install_requires vs Requirements files

classifier

这个参数提供了一系列的分类,在PyPI上会将其放入不同的目录中讲项目进行归类。
具体的categories的名称和规则参考:https://pypi.python.org/pypi?%3Aaction=list_classifiers

test_suite

这个参数可以帮助我们使用

python setup.py test

来跑单元测试,再也不需要单独再写一个脚本例如run_tests.py这样来跑单元测试了。
此参数的官方解释:

A string naming a unittest.TestCase subclass (or a package or module containing one or more of them, or a method of such a subclass), or naming a function that can be called with no arguments and returns a unittest.TestSuite. If the named suite is a module, and the module has an additional_tests() function, it is called and the results are added to the tests to be run. If the named suite is a package, any submodules and subpackages are recursively added to the overall test suite.

也就是说这个参数可以接受多种类型的参数:

接收unittest.TestCase子类,我们可以讲所有单元测试写入一个测试用例中,然后import进来,再传你给test_suite
接收函数对象,此函数对象没有任何参数,且返回一个unittest.TestSuite.这样我们就可以单独写一个函数,将多个测试用例合并成一个suite然后返回,然后再将函数import进来传给test_suite。

模块和包名称,我就是使用这种方式,之前自己的测试都是分开的多个脚本,这样我添加一个__init__.py就可以将其变成一个包,将包名传给test_suite,setuptools就会神奇的将此包下的所有测试全部跑一边,这样我以后再加测试脚本的时候直接就添加新的脚本就好了,其他的都不需要改动了。

运行效果:

zjshao@SHAO-PC:/mnt/d/Dropbox/Code/CentOS_code/VASPy$ python setup.py test
running test
running egg_info
creating vaspy.egg-info
writing vaspy.egg-info/PKG-INFO
writing top-level names to vaspy.egg-info/top_level.txt
writing dependency_links to vaspy.egg-info/dependency_links.txt
writing manifest file 'vaspy.egg-info/SOURCES.txt'
reading manifest file 'vaspy.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'vaspy.egg-info/SOURCES.txt'
running build_ext
test_compare (tests.incar_test.InCarTest)
Make sure we can compare two InCar objects correctly. ... ok
test_eq (tests.incar_test.InCarTest)
Test __eq__() function. ... ok
...
此处省略若干输出
 
----------------------------------------------------------------------
Ran 22 tests in 3.574s
 
OK

发布自己的python包

1. 首先先去PyPI注册帐号

2. 配置~/.pypirc如下:

[distutils]
index-servers =
  pypi
  pypitest
 
[pypi]
username:ShaoZhengjiang
password:mypassword
 
[pypitest]
username:ShaoZhengjiang
password:mypassword

3. 然后注册并上传自己的包到测试服务器

pypi提供了一个测试服务器,我们可以在这个测试服务器上做测试。

python setup.py register -r pypitest

然后

python setup.py sdist upload -r pypitest

若没有问题我们应该不会得到任何错误。

4. 上传至PyPI

若上面的测试成功,我们就可以按照相同的步骤将包注册并上传。

python setup.py register -r pypi
python setup.py sdist upload -r pypi

Ok,之后我们就可以在PyPI(https://pypi.python.org/pypi/vaspy/)上看到我们自己的包了。

Python 相关文章推荐
python3.3实现乘法表示例
Feb 07 Python
用Python输出一个杨辉三角的例子
Jun 13 Python
Python聚类算法之DBSACN实例分析
Nov 20 Python
python的mysqldb安装步骤详解
Aug 14 Python
多个应用共存的Django配置方法
May 30 Python
Python subprocess模块常见用法分析
Jun 12 Python
python读取文本中的坐标方法
Oct 14 Python
简单了解python数组的基本操作
Nov 26 Python
Django中ORM找出内容不为空的数据实例
May 20 Python
python Gabor滤波器讲解
Oct 26 Python
python 利用matplotlib在3D空间绘制二次抛物面的案例
Feb 06 Python
python中random模块详解
Mar 01 Python
在python的类中动态添加属性与生成对象
Sep 17 #Python
Python中字符串的处理技巧分享
Sep 17 #Python
Python中对象迭代与反迭代的技巧总结
Sep 17 #Python
发布你的Python模块详解
Sep 15 #Python
Python selenium 三种等待方式解读
Sep 15 #Python
玩转python selenium鼠标键盘操作(ActionChains)
Apr 12 #Python
Python selenium文件上传方法汇总
Nov 19 #Python
You might like
PHP stristr() 函数(不区分大小写的字符串查找)
2010/06/03 PHP
destoon实现公司新闻详细页添加评论功能的方法
2014/07/15 PHP
Thinkphp实现站点静态化的方法详解
2017/03/21 PHP
PHP切割汉字的常用方法实例总结
2019/04/27 PHP
效率高的Javscript字符串替换函数的benchmark
2008/08/02 Javascript
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
自用js开发框架小成 学习js的朋友可以看看
2010/11/16 Javascript
JS脚本defer的作用示例介绍
2014/01/02 Javascript
改变状态栏文字的js代码
2014/06/13 Javascript
js实现仿百度汽车频道选择汽车图片展示实例
2015/05/06 Javascript
JQ技术实现注册页面带有校验密码强度
2015/07/27 Javascript
vue小图标favicon不显示的解决方案
2017/09/19 Javascript
JS计算输出100元钱买100只鸡问题的解决方法
2018/01/04 Javascript
jquery 通过ajax请求获取后台数据显示在表格上的方法
2018/08/08 jQuery
vue拖拽排序插件vuedraggable使用方法详解
2020/08/21 Javascript
node.js中express模块创建服务器和http模块客户端发请求
2019/03/06 Javascript
Vue项目总结之webpack常规打包优化方案
2019/06/06 Javascript
微信小程序后台持续定位功能使用详解
2019/08/23 Javascript
Node.js创建一个Express服务的方法详解
2020/01/06 Javascript
vue实现一个6个输入框的验证码输入组件功能的实例代码
2020/06/29 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
[03:46]DAC趣味视频-中文考试.mp4
2017/04/02 DOTA
在Django的模板中使用认证数据的方法
2015/07/23 Python
matplotlib设置legend图例代码示例
2017/12/19 Python
python-str,list,set间的转换实例
2018/06/27 Python
Python 读取串口数据,动态绘图的示例
2019/07/02 Python
Django单元测试中Fixtures的使用方法
2020/02/26 Python
Python绘图之柱形图绘制详解
2020/07/28 Python
CSS3实现彩色进度条动画的示例
2020/10/29 HTML / CSS
HTML5 Canvas中使用路径描画二阶、三阶贝塞尔曲线
2015/01/01 HTML / CSS
受外贸欢迎的美国主机:BlueHost
2017/05/16 全球购物
美国排名第一的泳池用品直接来源:In The Swim
2019/09/23 全球购物
类、抽象类、接口的差异
2016/06/13 面试题
艺术教育实施方案
2014/05/03 职场文书
新闻通讯稿范文
2015/07/22 职场文书
golang特有程序结构入门教程
2021/06/02 Python