Python包管理工具小结

时间:2022-09-01 12:52:19

此文已由作者张耕源授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

作为一名接触Python有一段时间的初学者,越来越体会到Python的方便之处,它使人能更
多的关注业务本身的逻辑,而不用太纠结语言层面的技巧与细节。然而,随着服务的规模
变得越来越大,如何方便快速地制作与发布一个Python软件包则越来越成为一个让人头疼
地问题,特别是像Openstack这种相对复杂、各种依赖也很多的Python项目,到目前也没有
发现特别完美的解决方案。这里将尝试对Python的包管理工具做一个小结,为将来更好的
解决这个问题提供思路。

setuptools

setuptools1 是Python提供的最基本的包管理工具,后面提到的其他更高层次的Python
包管理工具都是在它的基础上实现的。曾经Python还有其他各种各样类似功能的包管理工
具,比如distribute、distutils等等,对有选择困难症的同学非常不友好,不过目前绝大
多数Python项目都开始统一使用setuptools,其他工具已经被慢慢合并/遗弃了。

setuptools的常见使用方式是在Python项目中新建一个setup.py:

from setuptools import setup, find_packagessetup(
    name = "HelloWorld",
    version = "0.1",
    packages = find_packages("helloworld"),
)

在这个文件中通过setuptools提供的各种关键字描述项目的元信息,包括名字、版本、
文件等等。写好后就可以通过python setup.py [command]执行setuptools提供的各种子
命令,比如编译、安装、测试、制作各种格式的软件安装包等等。

当你拿到一份Python项目的源代码,如果它已经写好了setup.py,你就可以方便的通过
setuptools将它安装到系统:

$ python setup.py install

目前,使用setuptools制作的软件安装包常见格式有:

source distro

$ python setup.py sdist

binary distro: egg

$ python setup.py bdist_egg

binary distro: wheel

$ python setup.py bdist_wheel

以openstack/nova为例,对应的三种格式软件安装包分别为:

nova-12.0.0.0b2.dev251.tar.gz
nova-12.0.0.0b2.dev251-py2.7.egg
nova-12.0.0.0b2.dev251-py2.py3-none-any.whl

sdist和wheel格式的安装包都可以使用最常见的pip命令安装,egg还只能通过
比较老得easy_install命令安装。

$ pip install nova-12.0.0.0b2.dev251.tar.gz$ easy_install nova-12.0.0.0b2.dev251-py2.7.egg$ pip install nova-12.0.0.0b2.dev251-py2.py3-none-any.whl

pbr

从上面的例子里可以看到,setup.py本质上还是一个Python脚本,有诸多语法的限制。
当Python项目比较庞大和复杂时,setup.py就会变的非常难写与维护。
在Openstack中,新建了一个pbr2 项目来处理这个问题。通过使用pbr项目提供的维护与setup.py对应的setup.cfg文本配置文件来自动生成setup.py从而解决这个问题。

比如上面的例子,切换到pbr就会变成这样:

setup.py

from setuptools import setupsetup(
    setup_requires=['pbr'],
    pbr=True,
)

setup.cfg

[metadata]name = HelloWorldversion = 0.1

[files]packages =
    helloworld

当然,实际工程中,setup.cfg文件的内容会比这个例子复杂很多。

pip

setuptools解决了Python软件包的制作问题,那如何分发它们呢?Python本身提供了PyPI
基础设施与相应的pip3 命令行工具来做这件事。

你可以将生成好的软件包通过

$ python setup.py upload

通过网络上传到PyPI。
上传成功后,其他人就可以直接通过pip命令安装你上传的软件包:

$ pip install ${package_name}

virtualenv

提到了pip,就不得不提一下virtualenv4 ,这两个工具经常是在一起搭配使用的。

virtualenv的功能有点像Linux系统下的chroot命令,运行

$ virtualenv .venv

后,他会将最小安装一个Python运行环境到当前目录的.venv文件夹,内容包括.venv/bin
下的python、pip命令,.venv/lib下的python库目录等等。当你使用

$ . .venv/bin/activate

激活刚刚创建出来的这个virtualenv环境后,你执行的python相关的二进制命令其实都是
.venv/bin目录下(而不是系统路径下的),安装/引用的python库也都是在.venv/lib目录
下的。

这样子,使用virtualenv后可以让每个Python项目使用独立的Python运行环境,不会产生
几个项目间依赖冲突、污染操作系统Python库的问题。

wheel

wheel5 是众多Python软件安装包格式的一种,这里专门要把它单独拿出来说是因为它的
优点和好处确实很多,是Python官方推荐的新一代Python项目发布格式,个人也非常希望
目前所有PyPI上项目都能尽快提供wheel格式的安装包。新版本的pip已经可以直接从PyPI
上下载安装wheel格式的安装包了。

和老的egg6 格式相比,wheel能让人直观感受到的先进之处:

  • 不包含.pyc文件(预编译的.pyc文件偶尔会导致各种奇怪的问题,我们更希望他能在
    每次安装时在本地生成更新),当项目是纯Python项目时wheel和source distro基本
    没有什么区别。

  • 官方支持,pip命令可以直接安装wheel,但是不能处理egg。

  • 更丰富的软件包元信息,甚至包中的每个文件都有版本记录。

  • 更细致的包命名规则

和egg格式一样,wheel拥有的优点:

  • 单安装文件。你是希望从源码文件夹下执行一系列命令编译安装一个Python项目,还是
    直接通过一个文件安装呢?

  • 依赖处理。安装程序会帮你自动安装相关依赖的Python库。

  • 二进制发布格式。当项目包含需要编译生成的extension时,可以将编译好的
    .so/.dylib/.dll等动态链接库直接一并打包,实现“一次编译,到处运行”(在相同的
    平台上)的效果,而不是每次都在终端重新编译生成。这点在大规模服务器上批量部署
    Python程序项目非常重要。可惜的是,目前wheel仅在windows和mac os平台支持这个特
    性,Linux平台由于各种原因还不支持,希望PyPA能尽快解决吧。

这里有一份官方文档详细比较了wheel和egg: 7

Linux distros

上面总结了Python打包社区PyPA(Python Packaging Authority)本身提供的各种工具,
但是在各个Linux发行版中,出于和系统集成(比如各种配置文件、脚本的管理)、加强
包的管理(PyPI上的软件包都是开发者自行*上传的)等等原因,很多Linux发行版通常
也会制作维护各自平台上专有的Python项目安装包,比如Debian系的.deb格式安装包
等等。

由于各个Linux发行版的管理风格、系统路径、甚至默认的Python版本等等都大相径庭,
所以各种安装包的规格、内容也差别很大。

常见的Linux发行版里,Debian系的.deb格式和Redhat系的.rpm格式安装包属于比较严格和
保守的一派。它们通常会做严格的版本、依赖控制;维护项目相关的服务配置文件、
SysVinit/systemd、syslog、logrotate脚本等等;安装包会包含任何需要编译的二进制
文件(如.pyc文件、各种需要编译的c extension等),不需要在安装时进行本地编译;
使用Python2作为Python的默认版本,甚至在某些较老的Debian、CentOS的发行版中,
还在使用Python2.6/2.3。

而像ArchLinux这样比较激进的Linux发行版,安装包的管理就非常奔放。安装包通常只是
帮你指定一下依赖、任何软件和库都用最新版本(非常令人讨厌的,Python也默认使用
Python3)、Python项目的PKGBUILD里package()通常就一行
“python2 setup.py install ...”。

总结

上面基本把最近自己接触到的和Python相关的包管理工具介绍了一遍,而在实际操作中去
在服务器上批量发布部署Python项目,利用上面提到的这些工具,能想到的通常有下面
几种方式。

每次到这个时候,真的是非常羡慕Java/Go这些不用纠结这种问题的编程语言。

直接源码安装

适合在自己的开发调试机器上瞎搞的时候使用。

由于Python/pip本身的包管理功能比较弱,直接在服务器上用这种方法会给服务器的系统
安装一系列不可控制的Python依赖,并且可能破坏其他Python程序的依赖,导致其他
Python程序无法正常运行。装的时候方便,当你碰到问题想清理的时候可就蛋疼了,相信
维护服务器的SA也不太可能会让你这样做的。

virtualenv+源码直接安装

比较靠谱的办法,但是只适合单机部署。当服务器数量众多,如何实现批量部署发布就是
个困难的问题了。

virtualenv+源码打包发布

在virtualenv环境里安装好所有的Python文件,把整个virtualenv目录打包成一个单独的
tar包。发布时直接将这个tar包拷贝到目标服务器上解压安装。

目前一些知名的Openstack厂商,如Rackspace,就是通过这种方式在服务器上部署Python
项目的。

然而,这样做的缺点是,还需要做很多额外的工作去维护服务的配置文件、脚本、系统上
非Python相关的软件依赖(如kvm、libvirt、openvswitch)等等。

类似方法还有自建私有PyPI源,提前将Python项目打包上传到自建的PyPI源里。然后在
服务器上的virtualenv环境里通过自建的PyPI源安装。

使用Linux发行版本身的安装包

比如,Debian系的.deb安装包、Redhat系的.rpm安装包。它们能比较好的维护各种服务
配置文件、脚本,以及像kvm这样的非Python相关的依赖,我们目前也在使用这种方式。

然而,它也有很多问题,以我比较熟悉的Debian发行版为例:

  • 所有Python项目共用一套Python依赖。当有的Python项目想升级某个第三方库时,会
    因为破坏其他Python项目的依赖版本而无法实现。

  • 官方提供的软件版本比较旧。对于一个追求稳定的Linux发行版,这么做本身并无可厚
    非,但是有时候当你就是想用新一点版本时,就会感觉非常无奈,基本都要自己动手制
    作安装包。而且由于依赖的关系,可能你为了给一个软件制作新版本的安装包,需要再
    为其他10个依赖的项目制作新版本的安装包,然后又要为这10个依赖的项目再制作30个
    依赖的依赖的新版本安装包。。。

  • 学习成本比较高。Debian的安装包制作方法,除了官方十年前写的几份文档外,网上
    其他能找到的资料很少,学起来比较费力。Debian作为一个装机量较大的Linux发行版都
    是这样,相信其他发行版也是类似的情况。

virtualenv+源码+Linux发行版安装包打包发布

在virtualenv环境里安装好所有的Python文件,然后将整个virtualenv目录打包到单独的
一个Linux发行版的安装包内,同时在这个安装包内设置好相关的配置文件、脚本、系统
依赖。

理论上这种方法综合了上面两种方式的优点,目前正在调研中,然而相信实践过程中肯定
会踩到不少坑。

spotify公布了他们在Debian下使用这种方式解决Python项目发布问题的工具dh-virtualenv8 ,感兴趣的同学可以参考一下。

References

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 知物由学|虚假色情泛滥,人工智能可以做些啥?
【推荐】 关于数据库查询业务的几点思考

Python包管理工具小结的更多相关文章

  1. python 包管理工具

    python 包管理工具 Python当前的包管理工具链是 easy_install/pip + distribute/setuptools + distutils,显得较为混乱. 而将来的工具链组合 ...

  2. Python 包管理工具解惑

    Python 包管理工具解惑 本文链接:http://zengrong.net/post/2169.htm python packaging 一.困惑 作为一个 Python 初学者,我在包管理上感到 ...

  3. Python包管理工具和多版本环境管理

    1. Python包管理工具 在安装Python包的过程中,经常涉及到distutils.setuptools.distribute.setup.py.easy_install.easy_instal ...

  4. 转载:Python 包管理工具解惑

    Python 包管理工具解惑 本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本站部分原创和翻译文章提供m ...

  5. Python包管理工具pip的基本使用

    1.简介 pip 是一个Python包管理工具,主要是用于安装 PyPI 上的软件包,可以替代 easy_install 工具. 2.pip安装 如果你安装的Python 2 >=2.7.9 或 ...

  6. python包管理工具他们之间的关系

    python包管理工具之间的关系 现在的python包管理工具有很多,非常混乱,必须理清他们之间的关系才能更好的使用python构建强大的包关系系统工具. 首先:python官方推荐的第三方库是PyP ...

  7. Python | Pipenv官方推荐的python包管理工具

    原文地址:https://cloud.tencent.com/developer/article/1355672 Pipenv - 官方推荐的的python包管理工具. Pipenv是一款旨在将所有包 ...

  8. [转载]Python 包管理工具

    [转载]Python 包管理工具 最近由于机缘巧合,使用各种方法安装了一些Python包,所以对Python的包管理开始感兴趣.在网上找到一篇很好的文章:https://blog.zengrong.n ...

  9. python 包管理工具 pip 的配置

    近几年来,python的包管理系统pip 越来越完善, 尤其是对于 windows场景下,pip大大改善了python的易用性. https://www.cnblogs.com/yvivid/p/pi ...

随机推荐

  1. setTimeout调用带参数的函数的方法

    function test(s){    alert(s);}window.setTimeout(function(){test('str');},1000);这样就可以了...为什么是这样呢.因为s ...

  2. sql语句 关于日期时间、类型转换的东西

    (一) 1, select update_date, CONVERT(VARCHAR(30),update_date,111) jj ,CONVERT(VARCHAR(30),update_date, ...

  3. JavaMail 发送邮件

    JavaMail邮件发送 引用maven jar包 <dependency> <groupId>javax.mail</groupId> <artifactI ...

  4. bzoj3571————2016——3——12(最小乘积匹配)

    bzoj3571 传送门http://www.lydsy.com/JudgeOnline/problem.php?id=3571 题解: ——————来自伟大的thy大神  http://blog.c ...

  5. iOS获取所有机型

    1.手机系统版本:9.1 NSString* phoneVersion = [[UIDevice currentDevice] systemVersion]; 2.手机类型:iPhone 6 NSSt ...

  6. BZOJ 1593&colon; &lbrack;Usaco2008 Feb&rsqb;Hotel 旅馆 &lbrack;线段树&rsqb;

    传送门 题意: 操作1:找长为$len$的空区间并填满,没有输出$0$ 操作2:将$[l,r]$之间的区间置空 我真是太弱了这种线段树还写了一个半小时,中间为了查错手动模拟了$30min$线段树操作, ...

  7. Windows Server 2016-WinSer2016 Active Directory新增功能

    Windows Server 2016 Active Directory 域服务 (AD DS)新增很多功能用来提升Active Directory域及组织环境安全等,并帮助他们面向云的部署或混合部署 ...

  8. linux(Redhat7)安装Apache

    1.下载apache安装包以及安装依赖的包(apr.apr-util.pcre)wget https://mirrors.cnnic.cn/apache/httpd/httpd-2.4.37.tar. ...

  9. 浅谈Retrofit2&plus;Rxjava2

    近几年,Retrofit犹如燎原之火搬席卷了整个Android界.要是不懂Retrofit,简直不好意思出门...由于近几个项目都没用到Retrofit,无奈只能业余时间自己撸一下,写的不好的地方,还 ...

  10. 【git】提交到github不显示贡献小绿点问题的解决

    问题描述: 最近一直在用github来写博客,但是今天发现github上的contributions记录并没有我的提交记录. 经过一番百度和自行捣鼓发现了问题所在. 原因: 最近实习,公司给配电脑.原 ...