python模块的打包与发布小结
前言
昨天把自己的VASP文件处理库进行了打包并上传到PyPI,现在可以直接通过pip
和easy_install
来安装VASPy啦,
- VASPy的GotHub地址:https://github.com/PytLab/VASPy
- VASPy的PyPI地址:https://pypi.python.org/pypi/vaspy/
由于自己的记性真是不咋地,怕时间久了就忘了,于是在这里趁热打铁以自己的VASPy程序为例对python的打包和上传进行下总结。
VASPy包文件结构
首先写贴上来VASPy包的整个文件结构, 后面的内容都是以此为例进行说明:
1 | VASPy/ |
打包和安装第三方包的工具
- 这里我们需要借助
setuptools
和pip
等工具进行自己包的打包和发布以及安装,如果需要构建成wheel还需要安装wheel
模块。如果python版本>=2.7.9或者>=3.4,setuptools和pip是已经安装好的,可能需要进行更新到最新版本。1
pip install -U pip setuptools
- 可以使用包管理工具,例如
1
yum install pip
1
sudo apt-get install pip
- 通过
get-pip.py
脚本安装,如果检测到没有安装wheel
和setuptools
也会自动安装。具体的工具安装和介绍就不多讲了,可以请参考requirements for installing packages1
python get-pip.py
包中不同文件的作用
setup.py
这个文件是打包整个项目最重要的文件,它里面提供了两个主要的功能:
setup()
函数,此函数的参数指定了如何配置自己的项目。- 命令行工具,包括打包,测试,发布等。可以通过下面的命令查看;
1
python setup.py --help-commands
setup.cfg
此文件包含了构建时候的一些默认参数例如构建bdist_wheel
的时候的--universal
参数1
2[bdist_wheel]
universal=1
这样每次打包的时候就会默认使用--universal
参数了,效果类似:1
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
的内容:1
2
3
4
5include 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__.py
s使其成为一个包。
setup()
的参数
这里只介绍我使用的几个参数,其他参数的具体使用可以参考:https://docs.python.org/3/distutils/setupscript.html
name
1 | versions = "vaspy" |
是整个项目的名字,打包后会使用此名字和版本号。
version
1 | from vaspy import __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
这个参数可以帮助我们使用1
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就会神奇的将此包下的所有测试全部跑一边,这样我以后再加测试脚本的时候直接就添加新的脚本就好了,其他的都不需要改动了。
运行效果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/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包
首先先去PyPI注册帐号
配置
~/.pypirc
如下:1
2
3
4
5
6
7
8
9
10
11
12[distutils]
index-servers =
pypi
pypitest
[pypi]
username:ShaoZhengjiang
password:mypassword
[pypitest]
username:ShaoZhengjiang
password:mypassword然后注册并上传自己的包到测试服务器
pypi提供了一个测试服务器,我们可以在这个测试服务器上做测试。1
python setup.py register -r pypitest
然后
1
python setup.py sdist upload -r pypitest
若没有问题我们应该不会得到任何错误。
上传至PyPI
若上面的测试成功,我们就可以按照相同的步骤将包注册并上传。1
python setup.py register -r pypi
1
python setup.py sdist upload -r pypi
Ok,之后我们就可以在PyPI上看到我们自己的包了。(https://pypi.python.org/pypi/vaspy/)