我的目标是分发一个Python包,其中包含其他几个广泛使用的Python包作为依赖项。我的包依赖于编写良好的Pypi索引包,如pandas、scipy和numpy,并在setup.py中指定需要这些包的某些版本或更高版本,例如"numpy>=1.5"。
我发现,对于精通Unix的用户来说,即使在使用本应易于使用的包管理器时,安装像我这样的包也是非常令人沮丧的,而且几乎不可能的。我想知道是否有人可以提供一种替代这个痛苦过程的方法,或者我的经历是否反映了Python打包和分发的困难现状。
假设用户将您的软件包下载到他们的系统中。大多数人会尝试"天真地"安装它,使用类似的东西:
$ python setup.py install
因为如果你在谷歌上搜索关于安装Python包的说明,通常会出现这种情况。对于绝大多数用户来说,这将失败,因为大多数用户在Unix/Linux服务器上没有root访问权限。通过更多的搜索,他们将发现"--prefix"选项并尝试:
$ 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"
(这可能很困难)后,他们将尝试:
$ easy_install setup.py
这也会失败,因为用户通常没有在生产Unix服务器上全局安装软件的权限。通过更多的阅读,他们将了解"--user"
选项,并尝试:
$ easy_install setup.py --user
他们会得到错误:
usage: easy_install [options] requirement_or_url ...
or: easy_install --help
error: option --user not recognized
他们会非常困惑,为什么他们的easy_install
没有--user
选项,因为网上有明确的页面描述该选项。他们可能会尝试将easy_install
升级到最新版本,但发现它仍然失败。
如果他们继续咨询Python封装专家,他们会发现easy_install
有两个版本,两者都命名为"easy_install"
",以最大限度地增加混乱,但"distribute"的一部分和"setuptools"的另一部分".碰巧只有"distribute"
的"easy_install"
支持"--user"
,而绝大多数服务器/sys管理员都安装"setuptools"
的easy_install
,因此无法进行本地安装。请记住,"distribute"
和"setuptools"
之间的这些区别对于不是Python包管理专家的人来说是没有意义和难以理解的。
在这一点上,我甚至会失去90%的最坚定、最精明、最耐心的用户,他们试图安装我的软件包——这是理所当然的!他们想安装一个碰巧是用Python编写的软件,而不是成为最先进的Python包分发专家,这太令人困惑和复杂了。他们会放弃,并对浪费的时间感到沮丧。
继续询问更多Python专家的极少数用户将被告知他们应该使用pip/virtualenv
而不是easy_install
。安装pip
和virtualenv
并弄清楚这些工具是如何工作的,以及它们与传统的"python setup.py"
或"easy_install"
调用有何不同,这本身就很耗时,也很困难,对于那些只想安装一个简单的Python软件并使用它的用户来说,要求也太多了。即使是那些走这条路的人也会感到困惑,他们用easy_install
或setup.py install --prefix
安装的任何依赖项是否仍然可以用pip/virtualenv
,或者是否所有东西都需要从头开始重新安装。
如果一个或多个有问题的包依赖于安装与默认版本不同的Python版本,则会加剧此问题。要确保您的Python包管理器使用您想要的Python版本,并且所需的依赖项安装在相关的Python 2.x目录中,而不是Python 2.y目录中,这对用户来说将是一件非常困难的事情,他们肯定会在那个阶段放弃。
有没有一种更简单的方法可以安装Python软件,而不需要用户深入研究Python包、路径和位置的所有技术细节?例如,我不是一个Java用户,但我偶尔会使用一些Java工具,我不记得曾经担心过我安装的Java软件的X和Y依赖性,我也不知道Java包管理是如何工作的(我很高兴我没有——我只是想使用一个碰巧用Java编写的工具。),你只要得到它,它就会起作用。
Python有等效程序吗?以一种不依赖于用户必须追查所有这些依赖关系和版本的方式分发软件的方式?一种可能将所有相关包编译成自包含的东西的方法,可以下载并作为二进制文件使用吗?
我想强调的是,这种挫败感即使是在向精明的Unix用户分发包的狭隘目标下也会发生,这通过不担心跨平台问题等使问题变得更简单。我认为用户精通Unix,甚至可能了解Python,但只是不知道(也不想被人知道)Python包的来龙去脉,以及不同包管理器的无数内部复杂性/竞争。这个问题的一个令人不安的特性是,即使您的所有Python包依赖项都是众所周知的、编写良好且维护良好的Pypi可用包,如Pandas、Scipy和Numpy,也会发生这种情况。这并不是说我依赖于一些不正确格式的包的模糊依赖:相反,我使用的是许多人可能依赖的最主流的包。
如有任何帮助或建议,我们将不胜感激。我认为Python是一种很棒的语言,有很棒的库,但我发现几乎不可能以一种人们可以轻松在本地安装并运行的方式分发我用它编写的软件(一旦它有依赖项)。我想澄清的是,我正在编写的软件不是用于编程的Python库,而是具有可执行脚本的软件,用户可以将其作为单独的程序运行。谢谢
我们还开发依赖numpy、scipy和其他PyPI包的软件项目。不用说,目前用于管理远程安装的最佳工具是zc.buildout。它非常易于使用。你从他们的网站下载一个引导脚本,并将其与你的包一起分发。您编写一个"本地部署"文件,通常称为buildout.cfg
,解释如何在本地安装包。bootstrap.py
文件和buildout.cfg
都随您的包一起提供-我们在python包中使用MANIFEST.in
文件来强制使用PyPI分发的zip或tar球嵌入这两个文件。当用户将其解压缩时,它应该执行两个命令:
$ python bootstrap.py # this will download zc.buildout and setuptools
$ ./bin/buildout # this will build and **locally** install your package + deps
编译包并在本地安装所有依赖项,这意味着安装包的用户甚至不需要root权限,这是一个附加功能。脚本(通常)放在./bin
下,所以用户可以在那之后执行它们。zc.buildout
使用setuptools
与PyPI进行交互,因此您所期望的一切都可以开箱即用。
如果所有的能力都不够,你可以很容易地扩展zc.buildout
——你可以创建所谓的"配方",帮助用户创建额外的配置文件,从网上下载其他东西或实例化自定义程序。zc.buildout网站包含一个视频教程,详细解释了如何使用buildout以及如何扩展它。我们的项目Bob广泛使用buildout来分发科学使用的包。如果您愿意,请访问以下页面,其中包含我们的开发人员如何设置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/