Archive for December, 2017

Python 包管理工具总结

December 4th, 2017

最近一直使用elasticsearch-py 操作数据库,最开始我是clone的他的官方仓库,然后使用python setup.py install方式安装的,虽然也可以使用,调用他的包没有什么问题,但是在pycharm中一直出现红色下划线,当遇到参数错误的时候,也没有办法跳入接口,看内部实现,比较抓狂。。。。。

考虑到之前配置python包遇到很多小问题,这次一次性把技术债还了。

通过查资料,大致可以理出来distutils、setuptools、distribute、disutils2、distlib、pip这几个工具的出现先后:

  1. 首先出现的安装工具是distutils,distutils 是 python 标准库的一部分,我们在python工程中的setup.py就是利用distutils完成的,他的工作原理很简单,但是功能有限。
  2. 为了完善distutils工具,产生了setuptools,它包含了 easy_install 这个工具;其中 ez_setup.py 是 setuptools 的安装工具,ez 就是 easy 的缩写。我们可以是使用
    easy_install http://example.com/Package-1.2.3.tgz  .egg 方式安装。
  3. distribute 是 setuptools 的一个分支版本,目前distribute 又合并回了 setuptools 中。本质上是同一个东西。如果查看一下 easy_install 的版本,它本质上就是 distribute 。
  4. distutils2是一个新的distutils库,作为distutils代码库的一个分支。
  5. distlib是distutils2的一部分
  6. pip是目前 python 包管理的事实标准,2008年发布。用来替换 easy_install,但是它仍有大量的功能建立在 setuptools 组件之上。

以上工具中distutils、setuptools、distribute、pip是主流包管理器,disutils2、distlib还需要观察。

eggs Vs whl 

Eggs 格式是 setuptools 引入的一种文件格式,它使用 .egg 扩展名,用于 Python 模块的安装。而setuptools 可以识别这种格式。并解析安装它。

wheel 本质上是一个 zip 包格式,它使用 .whl 扩展名,用于 python 模块的安装,它的出现是为了替代 Eggs。

eggs和whl本质上都是压缩包,我们都可以通过修改后缀名,解压提取内容!但是在pip中不太推荐egg的安装方式,因为egg安装后,只是把这个egg安装包放到dist-package中,而whl本质是一种源码安装,安装后在dist-package中存在源码和同名的info文件来描述这个安装包,因此我们可以在调用的时候,查看接口,而egg在编译器看来就是一堆二进制数据。

拿elasticsearch-py源码包举例,从github上clone最新的源码到本地,我们可以使用python setup.py install 直接将egg安装到/usr/local/lib/python2.7/dist-package中,而源码放在elasticsearch-py源码中的build中,所以可以使用python setup.py sdist 将其压缩为egg,然后使用pip安装该egg。另外也可以将源码打成rpm : python setup.py bdist_rpm   exe: python setup.py bdist_wininst

但是还是推荐打成whl格式的安装包,python setup.py bdist_wheel 。这个会将源码安装到dist-package中。

依赖安装:setup.py和requirements.txt的对比 这篇文章主要参数了两种安装文件的异同,归纳起来就是setup.py无法灵活限定软件版本,而requirements.txt可以限定具体软件包的版本,可以配合setup.py实现。

requirements.txt:

--index https://pypi.python.org/simple/
-e https://github.com/foo/bar.git#egg=bar
-e .

比如 pip install -r requirements.txt 可以照常工作,它会先安装requirements路径下的bar包,然后继续开始解析抽象依赖,结合 –index 选项后转换为具体依赖然后再安装她们。

这个办法可以让我们解决一种类似这样的情形:比如有两个或两个以上的包在一起开发但是是分开发行的,或者说有一个尚未发布的包并把它分成了几个部分。如果顶层的包 依然仅仅按照“名字”来依赖的话,我们依然可以使用requirements.txt 来安装开发版本的依赖包。

 

参考

https://docs.python.org/3/distutils/introduction.html?highlight=distutils#a-simple-example

http://blog.csdn.net/lynn_kong/article/details/17540207

https://stackoverflow.com/questions/6344076/differences-between-distribute-distutils-setuptools-and-distutils2/14753678#14753678