我的目标是发布一个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"后,可能会比较困难,他们会尝试:
这也将失败,因为用户通常没有在生产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。安装pip和virtualenv,弄清楚这些工具是如何工作的,以及它们与传统的"python setup.py"或"easy_install"调用有什么不同,这本身就很费时,也很困难,而且对于那些只想安装一个简单的python软件并使用它的用户来说,这又是一个要求太多的问题。即使是那些走这条路的人,也会困惑于他们与easy_install或setup.py install --prefix安装的任何依赖项是否仍然可以与pip/virtualenv一起使用,或者是否需要从头重新安装。
这个问题恶化了
- 在我看来,最好的答案是以标准的方式分发它——也就是说,pip,因为easy_install被否决了(这意味着安装它需要一些知识,如您所说),然后让每个发行版的维护人员处理使安装该发行版更容易的问题——这意味着将有所不同,尽管一般来说这意味着通过包管理器单击安装,它将处理DEPS。
- 你说的发行版维护者是什么意思?我不明白这个评论。我也不知道在手册的安装部分该如何告诉我的用户。他们是否应该在启动之前彻底检查整个设置并使用virtualenv/pip?安装分发轻松安装?我甚至不知道该告诉他们什么。
- 实际上,每一个Linux发行版(以及以自制等形式出现的OS X)都有一个包管理器。这些是处理已安装软件的软件安装和维护的软件部分,软件包维护人员维护告诉系统如何安装软件并使其保持最新的软件包。通常,Linux操作系统的软件将作为源代码发布,然后包维护人员将创建一个包来处理最终用户的所有安装,以适应发行版的风格和设置。包维护人员将能够处理Python的分发方法。
- 这意味着,对于最终用户,安装过程将是sudo apt-get install some_python_package或sudo pacman -S some_python_package,但他们的包管理器工作正常。这是明智的,因为不同的发行版需要不同的东西——例如,arch默认情况下使用python 3,如果没有仔细打包以使用python 2,可能会破坏某些软件。另外,这在Python方面也在工作。看看PEP 427。
- @Lattyware:在由组共享的生产Linux服务器上,情况并非如此。如果您与许多其他人一起使用服务器/集群,那么您的系统管理员将有一种安装特定于他们的软件的方法。例如,许多服务器使用module add或use系统从路径中添加/删除软件。我从来没有在集群中工作过,用户可以直接访问像apt-get这样的包管理器。所以我不认为发行包经理能解决这个问题。
- 在这种情况下,服务器所有者提供了一个包管理器,所以重复了同样的事情。服务器所有者使用包管理器进行安装,最终用户使用服务器所有者提供的任何系统进行安装。
- @Lattyware:它不完全是一个包管理器,它只是一个可用包的列表,您可以"加载"或"卸载"到您的环境中。因此,他们可能以这种方式安装了python,或者安装工具易于安装,您可以执行"使用python2.7"或"使用易于安装"来访问易于安装。但是,一旦您可以通过这个系统轻松安装,我在文章中描述的所有问题都会再次出现。模块系统没有任何区别。
- 安装工具易于安装也有-用户,但仅限于最新版本。
- 这是一个非常相关的问题,被否决了。
- 2016,仍然没有一个简单的工作方式来分配一个Python程序/脚本/包,比如JAVA文件。
我们还开发依赖于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工具还不依赖于其他的python包(确切地说是为了避免安装问题),但它将在不久的将来出现,因此我们需要一个合适的解决方案,允许用户轻松地安装我们的工具。zc.buildout看起来是一个很好的解决方案,但它仍然需要用户1)下载包,2)解包,3)运行"python bootstrap.py"和4)运行buildout。你能不能用一个能完成所有工作的命令来实现它,例如,编写一个nastly setup.py脚本,使"easy-install-foo"可以与buildout一起工作?
- 我认为这是不可能的,你也不希望这是你必须保持的东西。构建依赖于设置工具,而不是相反。根据我的经验,最好的方法总是依赖于Pypi来分发包:它在那里,不需要任何成本,而且它是镜像的。我们在您的出版物上放置了一个指向PYPI包页面的链接。用户点击它,会看到一个不错的手册和一个绿色的下载按钮。您可以编写一个脚本,在一个快照中完成所有这些操作,但随后需要单独分发/维护。
- 在我们的例子中,我们已经有了一个元包,它结合了构成我们软件的三个包,请参见pypi.python.org/pypi/easybuild。多功能一体机脚本可以是meta包的一部分(现在基本上只有setup.py)。
- 用户仍然需要下载easybuild,解包,然后运行一些东西。为什么这个东西不能是buildout呢?
- 它可以,但我认为只需要运行一个命令的解决方案也可以工作。
- "easy-install-user easybuild"应该是这个命令,但正如我在寻找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。/
- 谢谢你的努力。考虑到python的一个原则是"应该有一个——最好只有一个——显而易见的方法来完成它。"我惊讶于(坏的)所有不同的,但相似的,相互连接的,打包我的代码以便于用户安装的选项。
- "python packaging用户指南"(pypug)旨在成为有关如何使用当前工具打包、发布和安装python发行版的权威资源。-packaging.python.org