【发布时间】: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。安装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 库,而是具有用户作为单独程序运行的可执行脚本的软件。谢谢。
【问题讨论】:
-
在我看来,最好的答案是以标准方式分发它 - 即
pip,因为easy_install已被弃用,(这意味着它需要一些知识,正如你所说, 来安装),然后让每个发行版的维护人员处理使该发行版的安装变得容易 - 这意味着什么会有所不同,尽管通常这意味着通过包管理器一键安装,这将处理 deps。 -
发行版维护者是什么意思?我不明白评论。我也不知道在手册的安装部分告诉我的用户什么。他们是否应该在开始之前彻底检查整个设置并使用 virtualenv/pip?安装分发easy_install?我什至不知道该告诉他们什么。
-
几乎每个 Linux 发行版(以及 OS X 以 homebrew 和其他形式)都有一个包管理器。这些是处理软件安装和已安装软件维护的软件,包维护者维护告诉系统如何安装软件并使其保持最新的包。通常,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这样的包管理器。所以我不认为分发包管理器能解决这个问题。
标签: python pip setuptools python-packaging distribute