【问题标题】:How to easily distribute Python software that has Python module dependencies? Frustrations in Python package installation on Unix如何轻松分发具有 Python 模块依赖项的 Python 软件?在 Unix 上安装 Python 包的挫折
【发布时间】:2013-01-17 21:10:09
【问题描述】:

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

我发现,对于 Python 打包方面专家的 Unix 精通用户(即使他们知道如何编写 Python)安装像我这样的包,即使在使用什么应该是易于使用的包管理器。我想知道是否有人可以提供这个痛苦过程的替代方案,或者我的经验是否只是反映了 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 黑客攻击和其他并发症。

继续安装过程,一旦用户尝试使用该软件包,使用 "setup.py install""--prefix" 的调用也会失败,即使它似乎已正确安装,因为其中一个依赖项可能丢失(例如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"”以便最大程度地混淆,但其中一部分是“分发”和“setuptools”的其他部分。恰好只有"distribute""easy_install"支持"--user",并且绝大多数服务器/系统管理员安装"setuptools"easy_install等本地将无法安装。请记住,"distribute""setuptools" 之间的这些区别对于不是 Python 包管理专家的人来说毫无意义且难以理解。

在这一点上,即使是最坚定、最精明和耐心尝试安装我的软件包的用户,我也会失去 90% 的用户——这是理所当然的!他们想安装一个碰巧用 Python 编写的软件,而不是成为最先进的 Python 包分发方面的专家,这太令人困惑和复杂了。他们会放弃并为浪费的时间感到沮丧。

继续询问更多 Python 专家的极少数用户将被告知他们应该使用pip/virtualenv 而不是easy_install。安装pipvirtualenv 并弄清楚这些工具是如何工作的,以及它们与传统的"python setup.py""easy_install" 调用有何不同,这本身就既费时又困难,而且对于那些只是想要的用户来说要求太多了安装一个简单的 Python 软件并使用它。即使是那些追求这条道路的人也会困惑于他们使用easy_installsetup.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 库,而是具有用户作为单独程序运行的可执行脚本的软件。谢谢。

【问题讨论】:

  • 在我看来,最好的答案是以标准方式分发它 - 即pip,因为easy_install已被弃用,(这意味着它需要一些知识,正如你所说, 来安装),然后让每个发行版的维护人员处理使该发行版的安装变得容易 - 这意味着什么会有所不同,尽管通常这意味着通过包管理器一键安装,这将处理 deps。
  • 发行版维护者是什么意思?我不明白评论。我也不知道在手册的安装部分告诉我的用户什么。他们是否应该在开始之前彻底检查整个设置并使用 virtualenv/pip?安装分发easy_install?我什至不知道该告诉他们什么。
  • 几乎每个 Linux 发行版(以及 OS X 以 homebrew 和其他形式)都有一个包管理器。这些是处理软件安装和已安装软件维护的软件,包维护者维护告诉系统如何安装软件并使其保持最新的包。通常,Linux 操作系统的软件将作为源代码发布,然后包维护者将创建一个包来处理最终用户的所有安装,以适应发行版的风格和设置。包维护者能够处理 Python 的分发方法。
  • 这意味着对于最终用户,安装过程将是sudo apt-get install some_python_packagesudo pacman -S some_python_package,但是他们的包管理器可以工作。这是明智的,因为不同的发行版需要不同的东西——例如,Arch 默认使用 Python 3,如果没有仔细打包以使用 Python 2,这种立场可能会破坏某些软件。此外,这正在 Python 上工作——边。看看PEP 427
  • @Lattyware:在由组共享的生产 Linux 服务器上,情况并非如此。如果您与许多其他人一起使用服务器/集群,您的系统管理员将有一种安装特定于他们的软件的方法。例如,许多服务器使用module adduse 系统从路径中添加/删除软件。我从来没有在一个集群上工作过,用户可以直接访问像apt-get 这样的包管理器。所以我不认为分发包管理器能解决这个问题。

标签: python pip setuptools python-packaging distribute


【解决方案1】:

我们目前正在努力让用户更轻松地开始以独立于平台的方式安装 Python 软件(特别是请参阅 https://python-packaging-user-guide.readthedocs.org/en/latest/future.htmlhttp://www.python.org/dev/peps/pep-0453/

目前,easy_install 的两个竞争版本的问题已得到解决,竞争的 fork “distribute”被合并到 setuptools 开发主线中。

目前关于 Python 软件跨平台分发和安装的最佳建议见此处:https://packaging.python.org/

【讨论】:

  • 感谢您的努力。考虑到 Python 原则之一是“应该有一种——最好只有一种——明显的方式来做到这一点。”,我对所有不同的方式感到惊讶(以一种糟糕的方式),但是相似且相互关联的选项来打包我的代码以方便用户安装。
  • '“Python 打包用户指南”(PyPUG) 旨在成为有关如何使用当前工具打包、发布和安装 Python 发行版的权威资源。 - packaging.python.org
【解决方案2】:

我们还开发依赖于 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 广泛使用构建来分发包以供科学使用。如果您愿意,请visit the following page 为我们的开发人员提供有关如何设置他们的 python 包以便其他人可以使用zc.buildout 在本地构建和安装它们的详细说明。

【讨论】:

  • 很好的答案,我肯定也会考虑扩建。尽管我们的 Python 工具还不依赖于其他 Python 包(正是为了避免安装问题),但它会在不久的将来实现,因此我们需要一个体面的解决方案来让用户轻松安装我们的工具。 zc.buildout 看起来是一个很好的解决方案,但它仍然需要用户 1) 下载包,2) 解包,3) 运行“python bootstrap.py”和 4) 运行 buildout。您能否以某种方式使其与一个可以完成所有任务的命令一起工作,例如,编写一个讨厌的 setup.py 脚本以使“easy_install foo”与 buildout 一起工作)?
  • 我认为这不是一件容易的事,您也不希望将其作为您必须维护的东西。构建依赖于 setuptools 而不是相反。根据我的经验,最好总是依赖 PyPI 进行包分发:它就在那里,不花钱,而且是镜像的。我们在您的出版物上放置了指向 PyPI 包页面的链接。用户点击它并看到一个漂亮的手册和一个绿色的下载按钮。您可以编写一个脚本一次性完成所有这些操作,但是您需要单独分发/维护它。
  • 在我们的例子中,我们已经有一个元包,它结合了构成我们软件的三个包,请参阅pypi.python.org/pypi/easybuild。多合一脚本可以是元包的一部分(现在基本上只有一个 setup.py)。
  • 用户还是需要下载easybuild,解压然后运行一些东西。为什么这个东西不能是buildout
  • 可以,但我认为只需要运行一个命令的解决方案也可以。
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 2021-08-23
  • 2014-11-22
  • 1970-01-01
  • 2018-05-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
相关资源
最近更新 更多