python项目打包部署

作者:张博 链接:https://www.zhihu.com/question/38081354/answer/81829426 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

浏览了以上所有人的答案,结合我平常在项目中的实际经验,谈谈我们团队的Python部署与发布流程。 目前很多公司还是用着石器时代的部署方式,怎么做呢?

1. 本地写代码,可能还没有virtualenv环境,是的其实我的老东家就是这样的。

2. 写一个脚本,安装需要的依赖到系统global环境,比如说 MySQLdb,
可能还要用apt-get 或者 yum 安装 python-dev 等等系统依赖,然后用pip 安装Python依赖。

3. 提交到svn/git,然后在测试机器上拉代码下来,运行脚本安装完依赖后,
如果是一个web项目,那么可能会直接 python web.py 8080 测试一下会不会报错,
测试完几个接口发现没问题,关掉测试机器。

4. 在生产环境把代码拉下来,或者通过部署系统,这里的部署系统一般是一个web页面,
能够将svn/git 上的代码打包后执行某一个脚本,来完成相应的部署,
也有可能是直接在机器上执行:
nohup python /path/to/python/main.py 2&1 > /dev/null & 
就启动来这个进程,然后自己可能还有一些业务监控来定时的监控这个脚本的存活状态。

5. 这里可能nginx已经配置好,你发布的是一个Django应用,那么打开浏览器,
查看网页无误。

ok,大功告成,我已经是一位合格的工程师了,我所理解的Python发布或者所有的发布不都是这样么,大家都是这样的。 如果你躺枪了,很好,我喜欢。 让我们看看这里的步骤缺少什么,我不仅仅从发布部署来说,我们谈谈一个理想的开发测试部署流程应该是怎样的。 1. 你应该有一个与线上环境一模一样的测试/开发机器,这里说的是系统环境而不是物理环境,比如说内核版本,Python版本,libc 版本,gcc 版本,shell 的环境等等都应该跟线上环境一样,这是保证代码质量的第一关,或许不应该叫做代码质量而是工程质量。有人可能会用eclipse或者其他的云云开发IDE,OK,没问题,保证系统是一样的,这里有点难。 2. 你应该有一个virtualenv环境,因为你的开发机器可能有多个项目,而且可能因为有些依赖版本问题,导致你发现不同的项目可能对同一个模块有不同版本的依赖,那么请你准备一个virtualenv环境,这是Python开发人员必备的。 3. 你应该把代码提交到git, 但是提交之前,你应该运行一般单元测试,单元测试包含两个部分,一是对整个项目里的所有代码有一个代码静态检查,例如pylint和pep8,第二部分是自动运行你的测试用例,因为你的一个小改动可能会影响到其他模块,而这一点你开发的时候没有意识到或者说你影响的模块不是你写的,这一点会让你写的代码更健壮,同时你更有信心对现有代码做新需求开发或者变动,这里,你可以把你的测试用例启动脚本活着命令加到git hook,这样每次commit的时候都会启动测试程序。 4. OK,保证测试用例通过后,你应该对这次写的代码很有信心了,那接下来就是把代码发布到测试环境。怎么做呢?

一个起码看起来合格的Python项目,大体上代码构建的目录应该是下面这样的,请参考《以正确的方式开源Python项目》 http://www.oschina.net/translate/open-sourcing-a-python-project-the-right-way 所有的代码文件都在pro中,其他都是项目发布于部署使用到的

-rwxr-xr-x 8 root root 4096 Sep 16 22:06 .git/
-rw-r--r-- 1 root root  434 Aug 10 16:00 .gitignore
-rw-r--r-- 1 root root  166 Jul 26 11:49 AUTHORS.md
-rw-r--r-- 1 root root  149 Aug 10 16:49 AUTHORS.rst
-rw-r--r-- 1 root root    0 Aug 10 16:49 CONTRIBUTING.rst
-rw-r--r-- 1 root root  245 Jul 26 11:59 HISTORY.md
-rw-r--r-- 1 root root  100 Aug 10 16:49 HISTORY.rst
-rw-r--r-- 1 root root 1453 Aug 10 16:49 LICENSE
-rw-r--r-- 1 root root  221 Aug 10 16:49 MANIFEST.in
-rw-r--r-- 1 root root 2964 Sep 12 11:19 Makefile
-rw-r--r-- 1 root root  239 Jul 26 11:49 README.md
-rw-r--r-- 1 root root  161 Aug 10 16:49 README.rst
drwxr-xr-x 2 root root 4096 Sep 16 22:06 conf/
drwxr-xr-x 2 root root 4096 Jul 26 11:59 deb-scripts/
drwxr-xr-x 2 root root 4096 Aug 23 15:52 doc/
drwxr-xr-x 8 root root 4096 Jan 16 13:12 pro/
-rw-r--r-- 1 root root   67 Aug 10 16:49 requirements-dev.txt
-rw-r--r-- 1 root root  284 Sep  2 15:34 requirements.txt
-rw-r--r-- 1 root root   22 Aug 10 16:49 setup.cfg
-rwxr-xr-x 1 root root 1406 Aug 10 16:49 setup.py*
drwxr-xr-x 4 root root 4096 Sep  2 17:30 utils/

我来解释一下这里的几个主要文件的作用. 这里的目录结构可能也跟我们团队的命名习惯有关.

conf/
conf/api.conf        // 项目配置
conf/logrotate.conf  // 日志轮转配置
conf/uwsgi.ini       // uwsgi 配置
conf/pro.upstart     // upstart 文件
conf/paste.ini       // paste 是用来部署uwsgi的一个中间件
conf/pro.cron        // 这里是crontab配置
conf/pro             // 其他配置,可能是允许执行的sudo命令等

deb-scripts/ 包含三个文件,这里我们说debian系统打包,Redhat 打 rpm 也同理。

eb-scripts/before-remove.sh     // 卸载前执行的脚本
deb-scripts/before-install.sh   // 安装前执行的脚本
deb-scripts/after-install.sh    // 安装后执行的脚本

doc/ 应该是项目的文档,这里推荐用sphinx 生成文档或者你自己写markdown也可以。

utils/ 下面包含了你可能需要用到的启动依赖,但是又不想每次都远程下载,且不是Python本身的依赖而是环境依赖,好吧,我们在utils下面放了一个virtualenv,执行virtualenv 就可以在本地生成一个virtualenv 环境了, 还有打包deb的脚本

Makefile 文件包含了很多命令,比如:

make test   // 执行单元测试和静态检查
make lint   // 执行 pylint
make pep    // 执行pep8 检查

一系列你经常用到的功能,都可以放到Makefile

2. 你应该把你的代码打成一个安装包,而不是一个压缩包,因为你要发布的是一个服务而不是一个模块,那么请你打成deb或者rpm包。 让我们看下打包代码:

#!/bin/sh
set -e

... // 省略了变量部分

if [ ! -d wheelhouse ]; then
	make wheel
fi

fpm -t deb -s dir -n "$PKG_NAME" -v "$VERSION" --prefix "$DEST_DIR" -f \
    --depends make \
    -x '*__pycache__' \
    -x '*.pyc' \
    -x '*.pyo' \
    -x '*.deb' \
    --before-install deb-scripts/before-install.sh \
    --after-install deb-scripts/after-install.sh \
    --before-remove deb-scripts/before-remove.sh \
    Makefile HISTORY.rst LICENSE AUTHORS.rst CONTRIBUTING.rst setup.cfg \
    MANIFEST.in README.rst setup.py utils requirements-dev.txt requirements.txt wheelhouse conf \
    $PYTHON_MODULES

一目了然,我们会把依赖打到 wheelhouse 里面,然后把 wheelhouse 一同打包到 deb 包,这里使用了 fpm 这个打包工具,需要安装ruby gem 来安装。 然后在你的 make install 命令可以包含下面这个:

pip install --use-wheel --no-index --find-links=wheelhouse -r requirement.txt

在你的 deb-scirpt/after-install.sh 里面,这个脚本会在deb包安装完成后执行,你应该在这里完成你的环境依赖安装还有你配置文件的加载,crontab的配置等,一个简单的脚本应该像下面这样:

#!/bin/sh
set -e

PREFIX=${PREFIX:-/opt/pro}
REPODIR=${REPODIR:-/data2/pro}
LOGDIR=${LOGDIR:-/data2/log/pro}
IMAGE_CACHE=${IMAGE_CACHE:-/data2/image/cache}
RUN_AS_USER=www-data

mkdir -p $REPODIR
mkdir -p $LOGDIR
mkdir -p $IMAGE_CACHE

chown -R "$RUN_AS_USER":"$RUN_AS_USER" $REPODIR
chown -R "$RUN_AS_USER":"$RUN_AS_USER" $LOGDIR
chown -R "$RUN_AS_USER":"$RUN_AS_USER" $IMAGE_CACHE

cd "$PREFIX"
# this project does not require install.
# make bootstrap install
make bootstrap
# install crontab, upstart job, logrotate config etc
install conf/pro.upstart /etc/init/pro.conf
install conf/logrotate.conf /etc/logrotate.d/pro
install -o root -m 0440 conf/pro /etc/sudoers.d/pro
install -o root -m 0644 conf/pro.cron /etc/cron.d/pro

start pro || true

3. 最后一步就是 start pro 这里使用upstart启动你的应用,你应该把你的应用交给系统而不是你自己 所以在 after-install 中,你需要把pro.conf这个文件安装到 upstart 目录. 4. 以上的所有步骤,还在你的本地,你需要做的是把代码发布到生产环境。这里你需要把你的deb包上传到私有apt源,然后就是发布到正式环境了。 5. 发布有几种方式:

1. 在机器上直接执行 apt-get install pro(不推荐)
2. 利用fabric执行远程命令发布(次不推荐)
3. 利用puppet发布(推荐)

前两者无需多说,利用puppet发布,可以使你的发布更佳规范,同时也可以对配置做更规范的管理,一些系统依赖,不是Python的而是系统本身的,比如有时候出现libpcre 这样的二进制系统依赖的时候,你应该利用puppet安装这些依赖,而不是手动去执行安装, 具体的 puppet 相关就不细说了。

OK,以上是个人比较推荐的Python流程,有错误请指正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏听雨堂

Apache+wsgi+flask部署

flask自带的web server是开发用途,并不适用与发布,需要借助专业的web服务器。 配置的坑无数,Apache部署,403禁止,莫名其妙无法访问,50...

40790
来自专栏吾真本

从“CI搭建兽”到“流水线即代码”操练目的准备工作CI搭建兽的辛苦手工工作10行代码搞定“CI搭建兽”的全部手工工作部署流水线与单件流

本文是2017年3月13日晚9点在“AHA面对面”线上分享的“单件流的力量-伍斌_Ben面对面”的操练步骤,这里是报名链接。

11420
来自专栏编程

年底总结一下Python WEB最好用的几个框架,让你有一个系统的了解

2017年就要过完了,我们来总结一下2017年最好用的17个Python Web框架 群内不定时分享干货,包括2017最新的python企业案例学习资料和零基础...

90180
来自专栏Java帮帮-微信公众号-技术文章全总结

Java(web)项目安全漏洞及解决方式【面试+工作】

78430
来自专栏玄魂工作室

实战-Fluxion与wifi热点伪造、钓鱼、中间人攻击、wifi破解

Fluxion是一个无线破解工具,这款软件可以帮你挤掉WiFi主人的网络让你自己登陆进去,而且WiFi主人怎么挤也挤不过你。这个工具有点像是Lin...

81260
来自专栏北京马哥教育

Windows10+Ubuntu双系统安装

最近因为毕设重新回归Ubuntu,手头有一台装了Win10的ThinkPad X240s,最终成功完成了Windows 10 教育版和Ubuntu Kylin ...

83960
来自专栏自由而无用的灵魂的碎碎念

实战解决使用ghost安装系统出现的各种问题

昨天使用ghost给人安装系统时,把另一个分区的数据都搞没了,安装完也只剩下一个分区,相信了解的同志们知道是什么原因。

15230
来自专栏美团技术团队

LsLoader——通用移动端Web App离线化方案

背景 由于JavaScript(以下简称JS)语言的特性,前端作用域拆分一直是前端开发中的首要关卡。从简单的全局变量分配,到RequireJS实现的AMD模块方...

470170
来自专栏数据和云

诊断案例:Oracle的Mutex机制和Cursor Pin S竞争分析

SQL的软解析也会带来性能问题么?我们都知道使用绑定变量,让SQL实现软解析是Oracle的最佳实践。那么大量的软解析会否带来负面的性能影响呢? 在以下数据库的...

37750
来自专栏FreeBuf

打狗棒法之:Cknife(C刀)自定义模式秒过安全狗

免责声明:本站提供安全工具、程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! 0x00 前言 很多朋友在使用Cknife时都误以为她只是菜刀的跨平...

34880

扫码关注云+社区

领取腾讯云代金券