这里只是用一个 Hello World 级别的模板类型项目,来说明下如何快速构建起来一个 Python 项目。且是在开源场景下发布,如果是闭源场景,再单独写一篇文章类似说明。
我们最终要完成的就是一个 Python 模块安装包。这里“完成”的定义是:实现功能、通过测试、发布到网上供别人使用。
比如:我们最后发布的是一个叫 onepiece 的 Python 库。
因为这里是允许开源的场景,所以就可以直接发布到 PyPI https://pypi.python.org/pypi 了,如图:
然后就可以直接用了,比如用 pip 方式安装:
$ pip install onepiece
onepiece 库中演示模块的功能很简单,就是打印一个字符串“One Piece”就完事,如下:
>>> from onepiece.example import hello_world
>>> hello_world()
>>> 'One Piece'
项目的源码直接查看 GitHub:https://github.com/akun/onepiece。
下面我们来看下,如何快速构建这么一个 Python 模块项目。
直接用项目模板来初始化项目,后续再单独写一篇文章,详细解释由模板生成的模块项目中各个文件的作用。因为用了模板,这里所谓的“快速构建”模板的历史积累起到很大的作用,我们要遵循 DRY(Don’t Repeat Yourself)这个原则。
你得先安装一个模板工具,后续会用到,如下:
$ pip install cookiecutter
或者如果你用的是 Ubuntu 的话,也可以:
$ apt-get install python-cookiecutter
然后,就可以用现成的 Python 项目模板初始化了,比如:
$ cookiecutter https://github.com/akun/aproject.git # 按提示输入内容即可
$ cd onepiece
$ virtualenv onepiece_venv
$ source onepiece_venv/bin/activate
$ make
$ git init
$ git add .
$ git commit # 比如日志是:chore: init project
我们直接用 GitHub,直接在上面新建个项目,就叫 onepiece,然后把 Git 本地仓库推送到 Git 远程仓库:
$ git remote add origin https://github.com/akun/onepiece.git
$ git push origin master
然后从 GitHub 上查看第一次提交的结果吧:https://github.com/akun/onepiece
就这样 first commit 就包含了一个完整的初始项目了,然而还没“完成”。
下列原则可以参考下:
因为是个示例,所以这里实现的功能就很简单了,就是打印一个字符串,代码如下:
#!/usr/bin/env python
# coding=utf-8
def hello_world():
return 'One Piece'
同样,测试代码也很简单,代码如下:
#!/usr/bin/env python
# coding=utf-8
from unittest import TestCase
from onepiece.example import hello_world
class HelloWordTestCase(TestCase):
def test_hello_world(self):
self.assertEqual('One Piece', hello_world())
独立一节来说,就是为了说明构建中测试是必须的环节,在这里,测试也很简单:
$ make test
可以看到所有测试用例在 Python 2 和 Python 3 下都通过,测试覆盖率是 100%,如下:
GLOB sdist-make: /home/kun/projects/pm/pm/onepiece/setup.py
py27 inst-nodeps: /home/kun/projects/pm/pm/onepiece/.tox/dist/onepiece-0.1.0.zip
py27 installed: coverage==4.5.1,future==0.16.0,httpretty==0.8.14,nose==1.3.7,onepiece==0.1.0,pkg-resources==0.0.0
py27 runtests: PYTHONHASHSEED='1283052189'
py27 runtests: commands[0] | nosetests -c nose.cfg
...E..
======================================================================
ERROR: test_do_print_example (tests.test_main.MainTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/kun/projects/pm/pm/onepiece/tests/test_main.py", line 16, in test_do_print_example
text = main.do_print_example()
File "/home/kun/projects/pm/pm/onepiece/onepiece/main.py", line 15, in do_print_example
print(text)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
Name Stmts Miss Cover
------------------------------------------
onepiece/__init__.py 1 0 100%
onepiece/example.py 2 0 100%
onepiece/main.py 22 0 100%
------------------------------------------
TOTAL 25 0 100%
----------------------------------------------------------------------
Ran 6 tests in 0.097s
FAILED (errors=1)
ERROR: InvocationError: '/home/kun/projects/pm/pm/onepiece/.tox/py27/bin/nosetests -c nose.cfg'
py3 inst-nodeps: /home/kun/projects/pm/pm/onepiece/.tox/dist/onepiece-0.1.0.zip
py3 installed: coverage==4.5,future==0.16.0,httpretty==0.8.14,nose==1.3.7,onepiece==0.1.0,pkg-resources==0.0.0
py3 runtests: PYTHONHASHSEED='1283052189'
py3 runtests: commands[0] | nosetests -c nose.cfg
......
Name Stmts Miss Cover
------------------------------------------
onepiece/__init__.py 1 0 100%
onepiece/example.py 2 0 100%
onepiece/main.py 22 0 100%
------------------------------------------
TOTAL 25 0 100%
----------------------------------------------------------------------
Ran 6 tests in 0.056s
OK
海贼王(One Piece)
___________________________________ summary ____________________________________
ERROR: py27: commands failed
py3: commands succeeded
这里演示的是一个很简单的单元测试,Python 的单元测试可以详见:《 Python 中的单元测试 》
独立一节来说,也是为了说明构建中文档是必须的环节,对于一个初始的项目,文档也很简单,大致包括:
推荐用 Sphinx 写技术文档,尤其你写的是 Python 项目。当然,MarkDown 也很流行,很多人习惯用这个写文档。用 Sphinx 写技术文档,详见: 《 用 Sphinx 编写技术文档 》。
到了最重要的一个环节了,发布 Python 模块库到 PyPI,直接:
$ make sdist
想了解 make sdist 中具体命令,后续再写一篇如何发布到 PyPI,这里不展开说明。
为什么说发布很重要,原因很简单,你不发布,那前面那些对用户来说相当于没有发生。
我们用到的工具或服务有这些:
配套工具和配套服务,前面提过,后续的文章中详细讲解模板里的文件时候再一并讲解,可以先简单看下这里: 《 做开源软件项目会用到的服务简介 》,对配套服务有简单介绍。
最后记住,大家一定要根据自己的需要形成自己的模板。
注解
这篇是个人总结的《软件构建实践》系列的一篇文章,更多更新内容,可以直接在线查看:http://pm.readthedocs.io。并且部分内容已经公布在 GitHub 上:https://github.com/akun/pm