关于pip:如何轻松分发具有Python模块依赖关系的Python软件?

How to easily distribute Python software that has Python module dependencies? Frustrations in Python package installation on Unix

我的目标是发布一个Python包,它有几个其他广泛使用的Python包作为依赖项。我的包依赖于编写良好的Pypi索引包,如pandas、scipy和numpy,并在setup.py中指定需要这些包的某些版本或更高版本,例如"numpy>=1.5"。

我发现,对于那些不擅长Python打包(即使他们知道如何编写Python)的懂Unix的用户来说,安装像我这样的包是非常令人沮丧的,几乎不可能的,即使在使用那些应该易于使用的包管理器时也是如此。我想知道是否有人可以提供这种痛苦的过程的替代方法,或者我的经验只是反映了当前Python打包和分发的非常困难的状态。

假设用户将您的包下载到他们的系统上。大多数人会尝试"幼稚地"安装它,方法如下:

1
$ python setup.py install

因为如果你在谷歌上搜索关于安装python软件包的说明,这通常就是你想要的。对于绝大多数用户来说,这将失败,因为大多数用户在其UNIX/Linux服务器上没有根访问权。通过更多搜索,他们将发现"-prefix"选项并尝试:

1
$ python setup.py install --prefix=/some/local/dir

由于用户不知道python打包的复杂性,他们将选择一个任意的目录作为--prefix的参数,例如"~/software/mypackage/"。它不会是所有其他python包所在的一个干净的目录,因为同样,大多数用户都不知道这些细节。如果他们安装另一个软件包"myotherpackage",他们可能会通过"~/software/myotherpackage",你可以想象这会导致令人沮丧的PYTHONPATH黑客攻击和其他并发症。

继续安装过程,一旦用户尝试使用该包,即使该包似乎已正确安装,使用"--prefix""setup.py install"的调用也将失败,因为其中一个依赖项可能丢失(如pandas、scipy或numpy),并且未使用包管理器。他们将尝试单独安装这些包。即使成功,由于提供给"--prefix"的非标准目录,软件包也不可避免地不在PYTHONPATH中,患者用户也可以修改PYTHONPATH以使依赖项可见。

在这个阶段,一个精通Python的朋友可能会告诉用户,他们应该使用像主流管理器"easy_install"这样的包管理器来安装软件并处理依赖关系。安装"easy_install"后,可能会比较困难,他们会尝试:

1
$ easy_install setup.py

这也将失败,因为用户通常没有在生产Unix服务器上全局安装软件的权限。通过更多的阅读,他们将了解"--user"选项,并尝试:

1
$ easy_install setup.py --user

他们会得到错误:

1
2
3
4
usage: easy_install [options] requirement_or_url ...
   or: easy_install --help

error: option --user not recognized

他们会非常困惑,为什么他们的easy_install没有--user选项,其中有明确的在线页面描述该选项。他们可能会尝试将他们的easy_install升级到最新版本,但仍然失败。

如果他们继续向Python打包专家咨询,他们会发现有两个版本的easy_install,两个版本都命名为"EDOCX1"(16),以便最大程度地混淆,但其中一个版本是"distribute"(分发)版本,另一个版本是"setuptools"(安装工具)。碰巧只有"distribute""easy_install"支持"--user",绝大多数服务器/sys管理员安装"setuptools"easy_install,因此无法进行本地安装。请记住,对于不擅长python包管理的人来说,"distribute""setuptools"之间的区别毫无意义,也难以理解。

在这一点上,即使是最坚定、最精明、最耐心的尝试安装我的软件包的用户,我也会损失90%——这是正确的!他们想安装一个恰好用python编写的软件,而不是成为最先进的python包分发领域的专家,这太复杂了。他们会放弃,对浪费的时间感到沮丧。

继续询问更多python专家的少数用户会被告知,他们应该使用pip/virtualenv,而不是easy_install。安装pipvirtualenv,弄清楚这些工具是如何工作的,以及它们与传统的"python setup.py""easy_install"调用有什么不同,这本身就很费时,也很困难,而且对于那些只想安装一个简单的python软件并使用它的用户来说,这又是一个要求太多的问题。即使是那些走这条路的人,也会困惑于他们与easy_installsetup.py install --prefix安装的任何依赖项是否仍然可以与pip/virtualenv一起使用,或者是否需要从头重新安装。

这个问题恶化了


我们还开发依赖于numpy、scipy和其他pypi包的软件项目。现在管理远程安装的最佳工具是zc.buildout。它很容易使用。你可以从他们的网站下载一个引导脚本,然后将它与你的包一起分发。您编写了一个"本地部署"文件,通常称为buildout.cfg,它解释了如何在本地安装包。您将bootstrap.py文件和buildout.cfg与您的软件包一起发送-我们在python软件包中使用MANIFEST.in文件强制使用pypi分发的zip或tar球嵌入这两个文件。当用户解包时,它应该执行两个命令:

1
2
$ python bootstrap.py # this will download zc.buildout and setuptools
$ ./bin/buildout # this will build and **locally** install your package + deps

包被编译,所有依赖项都在本地安装,这意味着安装包的用户甚至不需要根权限,这是一个附加功能。脚本(通常)放在./bin下,这样用户就可以在此之后执行它们。zc.buildout使用setuptools与pypi进行交互,因此您所期望的一切都是现成的。

如果所有的能量都不够的话,你可以很容易地扩展zc.buildout—你创建了所谓的"配方",可以帮助用户创建额外的配置文件,从网络上下载其他东西,或者实例化自定义程序。buildout网站包含一个视频教程,详细说明了如何使用buildout以及如何扩展它。我们的项目Bob广泛利用建筑来分发科学使用的包。如果您愿意,请访问下面的页面,其中包含我们的开发人员如何设置他们的python包的详细说明,以便其他人可以使用zc.buildout在本地构建和安装它们。


我们目前正在努力使用户更容易以独立于平台的方式开始安装python软件(具体请参见https://python-packaging-user-guide.readthedocs.org/en/latest/future.html和http://www.python.org/dev/peps/pep-0453/)

目前,两个竞争版本的easy-install的问题已经解决,竞争的fork"distribute"被合并到setuptools开发主线中。

关于跨平台发布和安装python软件的最佳建议,请参见:https://packaging.python.org。/