暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

工程化你的Python项目

写程序的康德 2016-08-05
832

现代软件开发越来越复杂,如果还单纯的认为学习软件开发就是学习某某编程语言那估计最多只能写写“Hello World”之类的程序了。我不觉得这种“复杂”是一种无病呻吟的病态,相反我认为这是软件开发技术的进步。系统越来越复杂,团队协作也越来越突出,这就决定了我们的工具也越来越复杂。工程化可以帮助我们的项目更加规范,让新成员更加容易理解项目。这篇文章里我会结合国情来介绍一些Python工程化心得。

工程结构

python-skeleton
├── README.md #
├── docs #文档
├── etc #示例配置文件
├── python_skeleton #项目所有代码
└── tests #测试代码

上面是我的工程结构,下面我们就要针对这个工程来实现工程化

import的正确姿势

这样的代码结构就是import的灾难,除了使用相对引用之外没有别的办法,所以这不是一种好的实践。第一步我们先给工程增加一个setup.py


这么多配置项没人能记得住,所以一般情况下我们可以从别的工程中复制setup.py。long_description
是一段很长的描述,所以我直接从README.md中读取整个项目的描述
packages
描述了哪些Python的包被打包,find_packages会查找当前工程下所有的Python包,通过exclude
剔除了不参与打包的。例子中就是单元测试、文档和示例配置
有了setup.py之后我们执行python setup.py develop
,这条命令会在site-package中建立一个link,指向我们当前的工程,所以我们的代码就可以使用绝对引用了。


python_skeleton是我项目所有源代码所在的包

单元测试、单元测试

单元测试被所有软件工程强调,所以作为工程化的一部分我们必须要给出单元测试的最佳实践。我的单元测试代码都在tests包,解决了import的问题后它是可以直接在IDE中执行了。但是一个一个的执行测试用例是非常麻烦的,所以我们希望通过python setup.py test
来一次执行所有的单元测试这样。


修改setup.py,添加一句。我比较懒,所以直接用python unittest 作为单元测试工具,如果你用nose作为单元测试工具需要写两句


test_require指定了测试的依赖,在执行python setup.py test
的时候会首先下载依赖然后再执行测试。

添加依赖

python最大的特点就是提供了非常非常丰富的第三方包,例如:我的代码中使用python-click。随着项目的开发势必还会增加更多第三方包,如果一个一个的安装那就太原始了。所以通过工程化我希望可以让新加入的小伙伴执行一句pip install -r requirements.txt
就可以自动安装所有依赖。


我们新建一个requirements.txt
,里面写上我们需要的依赖,执行pip的时候直接通过文件安装依赖。
setup.py中也会有依赖,当我们执行python setup.py install
的时候这些依赖会被安装到当前系统中。所以我们希望setup.py中的依赖和requirements.txt的依赖保持一致。


生成命令行工具

这个功能非常酷,我希望给我的程序增加一个命令行。用户输入:python-skeleton就可以执行我的程序了。


setup.py新增加一条,python-skeleton是命令名称,python_skelecton.cli是类,main是要执行的方法。


我使用python-click为项目增加了两个参数分别指定配置文件和日志配置文件。默认是使用/etc下面的

复制配置

命令行工具自动生成了,我希望还可以把代码中的两个配置实例


复制到系统的/etc/python-skeleton中。这样安装的时候我们只需要执行python setup.py install
就可以成功安装命令行脚本、自动复制配置文件了,简直是妙不可言。

总结一下

总结一下,到目前为止我们有setup.py、requirements.txt两个文件。通过这两个配置我们可以

  • python setup.py develop来安装开发环境,这样代码里面就可以使用绝对应用

  • 通过pip install -r requirements.txt来安装依赖

  • 发布的时候通过python setup.py install在目标系统上自动生成命令行脚本,复制配置文件,自动安装依赖

打包

到目前为止我们可以通过python setup.py sdist
来生成压缩文件


安装的时候只需要解压这个文件,然后执行python setup.py install


DUANG,我们收到一个错误。提示我们README.md文件找不到,如果我们查看发现压缩文件里面没有README.md和requirements.txt文件。我们的setup.py脚本是通过读取这两个文本文件生成配置的,所以在打包的时候需要把这两个文件也给打包进去。通过新增MANIFEST.in我们实现这个
再执行打包,我们的压缩里面就会有这两个文件

离线安装

通过上面的步骤我们生成的压缩包只有我们的代码,如果发布到生成环境时python setup.py install
会帮我们自动下载依赖。遗憾的是——在我朝,通常生产服务器都是没有网络的。所以我们希望可以通过离线的方式把第三方pip下载下来。
通过执行pip download -r requirements.txt -d ./pipcache
我们可以把依赖下载到pipcache文件夹中(请确保pipcache文件夹存在)
在生产环境我们使用pip install --no-index --find-links=pipcache -r requirements.txt
通过本地文件夹安装依赖

自动化

好了,到这里我们的自动化已经完成了。

  • 开发环境

1. python setup.py develop链接文件,解决import的问题
2. pip install -r requirements.txt 安装依赖
3. pip download -r requirements.txt -d ./pipcache 下载离线依赖(可选)

  • 生产环境

1. pip install --no-index --find-links=pipcache -r requirements.txt离线安装依赖(可选)
2. python setup.py install安装系统,该命令会生成命令行脚本,复制配置文件

这些命令都太长了,我希望通过一个脚本自动化打包,清除临时文件(删除pyc,egg等临时文件),同时为部署的时候生成一个脚本(毕竟那条离线安装的命令太长了。。。。)所以我写了一个Makefile

PIP太慢

通过为脚本增加-i http://pypi.douban.com/simple --trusted-host pypi.douban.com
选项可以加速PIP的下载。具体参考我的github。

最后

最后贡献出所有的代码,我的github上

https://github.com/fireflyc/python-skeleton


欢迎关注公众账号了解更多信息“写程序的康德——思考、批判、理性”


文章转载自写程序的康德,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论