setuptools vs. distutils:为什么distutils仍然存在?

203

Python有一些工具可以用来打包和描述项目,这些工具的历史比较混乱: 包括标准库中的distutils, distribute, distutils2, 以及setuptools(也许还有其他工具)。看起来distributedistutils2已经停止开发,而setuptools成为了主流,这就留下了两个竞争标准。

我理解setuptools提供了比distutils更多的选项(例如声明依赖关系、测试等),但它并没有被包含在Python标准库中(至少目前是这样的)。

Python Packaging User Guide[1]现在建议:

使用setuptools定义项目并创建源分发包。

并解释道:

虽然许多项目都可以使用纯distutils,但它不支持定义对其他项目的依赖关系,并且缺少几个方便的实用程序来自动正确填充包元数据,setuptools提供了这些实用程序。作为一个不在标准库中的工具,setuptools 也提供了一组更加一致的特性,适用于不同版本的Python,并且(与distutils不同),setuptools将会在所有支持的版本上更新为即将发布的“Metadata 2.0”标准格式。

即使是使用distutils的项目,当pip从源代码直接安装这些项目(而不是从预编译的wheel文件安装)时,它实际上也会使用setuptools来构建您的项目。

然而,查看各种项目的setup.py文件后可以发现这似乎并不是一个实际的标准。许多包仍然使用distutils,而那些支持setuptools的包通常会混合使用setuptoolsdistutils,例如通过回退导入:

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

接着尝试找到一种方法,可以编写一个可以同时被setuptoolsdistutils安装的设置。这通常包括各种容易出错的依赖检查方式,因为distutils不支持在设置函数中添加依赖。

为什么人们仍在做额外的努力来支持distutils - setuptools不在标准库中是唯一的原因吗?distutils的优点是什么,编写仅支持setuptoolssetup.py文件是否存在任何缺点。


8
distutils已经合并回setuptools,但是有些遗留应用程序是用distutils编写的,迁移到正确的标准需要付出成本。 - metatoaster
4
看起来distribute和distutils2已经停止更新,转而使用setuptools。现在的情况是,distribute只是setuptools的一个包装器,而distutils2已经废弃不用了。 - Kijewski
1
setuptoolsdistutils 的增强替代品,但请注意 "建议使用 pip 安装程序运行所有的 setup.py 脚本都使用 setuptools,即使脚本本身只导入 distutils"(来源 - user2314737
3
相关链接:distribute、distutils、setuptools和distutils2之间的区别?请问您需要翻译什么内容呢? - Stevoisiak
4个回答

106
请看这个 Stack Overflow 的问题。它很好地解释了所有的打包方法,并可能在一定程度上帮助回答您的问题:Differences between distribute, distutils, setuptools and distutils2? Distutils 仍然是 Python 中打包的标准工具。它包含在标准库中(Python 2 和 Python 3.0 到 3.3)。它对于简单的 Python 发布很有用,但缺少一些功能。它引入了可以在 setup.py 脚本中导入的 distutils Python 包。
Setuptools 是为了克服 Distutils 的局限性而开发的,它没有包含在标准库中。它引入了一个命令行实用程序 called easy_install。它还引入了 setuptools Python 包,可以在 setup.py 脚本中导入,以及 pkg_resources Python 包,可以在代码中导入,以定位与分发安装的数据文件。其中一个要注意的点是它对 distutils Python 包进行了 monkey-patch。它应该与 pip 配合良好。最新版本发布于 2013 年 7 月。
因此,正如您所看到的,应该优先使用 setuptools 而不是 distutils,并且我知道您提出问题的原因,但我认为 distutils 不会很快失去支持,因为它在许多情况下与一些流行的旧版程序一起使用。而且,正如您可能知道的,更改这些遗留程序中的这些内容可能会带来相当多的问题,例如不兼容性,这将导致开发人员不得不重新编写源代码。因此,还有一个事实是,distutils 是标准 Python 库的一部分,而 setuptools 不是。因此,如果您正在创建 Python 程序,则应在今天使用 setuptools,但请记住,没有 distutils,setuptools 就不会存在。

4
“Distutils仍然是Python中打包的标准工具。”与“Python软件包用户指南”相矛盾。 - cel
1
我不这么认为,它明确说明_setuptools_是标准吗?另外请注意,那句话是从我提供的网站引用的,所以那不是我的话。然而,这是一个观点,我和许多其他人都同意。 - user3429036
我授予您赏金,因为社区似乎同意您的观点。不幸的是,这个问题没有得到我希望它得到的那么多关注。 - cel
easy_install 是我拒绝使用 setuptools 的主要原因 - 在使用它的包中,它一直是一个巨大的问题源(重新打包更容易)。其他功能还可以。 - Stuart Gathman
1
显然,此时distutils已被弃用 - x-yuri

19
以下是来自 NumPy setup.py 的内容:事实是 setuptools 不在标准库中是其中之一的原因。
if len(sys.argv) >= 2 and ('--help' in sys.argv[1:] or
        sys.argv[1] in ('--help-commands', 'egg_info', '--version',
                        'clean')):
    # Use setuptools for these commands (they don't work well or at all
    # with distutils).  For normal builds use distutils.
    try:
        from setuptools import setup
    except ImportError:
        from distutils.core import setup

NumPy更喜欢使用setuptools,如果找得到的话。但是SciPy以前也是这样做的,直到它被patched在某些情况下优先选择distutils。引用提交日志:

Setuptools在测试脚本上设置了mode +x,因此Nose拒绝运行它们。最好不要这样做。

当然,setuptoolsdistribute之间的merger应该在适当的时间解决所有这些问题,但许多软件包仍需要支持Python 2.6安装。

3
distributesetuptools 的一个分支,现已合并回去。 - R4444

12

尽管setuptools无疑是更好的工具集,但我们仍然谈论和使用distutils有几个原因。

首先,distutils无处不在。如果您想构建一个模块以与他人共享,并且没有任何复杂的要求,那么它肯定可用于您的工作机器。这尤其重要,如果您必须支持较旧版本的python,或者发现自己在陌生的环境中工作。

其次,setuptools提供了对distutils的增强功能。因此,它是基于distutils工具集进行建模,并从那里获取所有结构。setuptools的文档假定读者熟悉distutils,并仅记录如何增强基本工具集。您可以将其视为distutils定义方言,而setuptools则增强该方言。

对于新项目,我的个人方法是假设我将使用distutils。只有当项目需要setuptools的功能时,我才升级。setuptools是distutils的插入替换,只需一行代码更改即可替换我的setup.py。


感谢您的回答。我认为可用性参数并不那么重要,因为setuptools安装可以引导。我认为如果distutils提供足够的功能,使用它是有意义的。但是,在我的观点中,混合使用distutils和setuptools并不是实现目标的非常干净的方式。尽管@larsmans在他的回答中展示了一些强制使用distutils完成某些任务的setuptools的困难。 - cel

11

基本上,这是由于责任分工的原因。

setuptools 不是 Python 标准库的一部分,因为它由第三方维护,而不是 Python 核心团队。这意味着,除其他事项外:

  • 它不在核心测试套件的覆盖范围内,也不是核心功能所依赖的
  • 它本身没有为附加模块设置核心标准(它们的位置、导入方式、C 扩展的二进制接口等)。
  • 它的更新和发布独立于 Python 发布。

实际上,核心团队已经缩小了 distutils 的范围,将“核心标准”和“最少必要编译”部分保留给自己,同时将所有超出此范围的内容(扩展编译器/包格式/任何支持等) 留给第三方。之前涵盖这些“扩展部分”的代码已经因向后兼容而过时。

来自 Distributing Python Modules — Python 2.7.12 documentation:

虽然直接使用distutils正在逐步淘汰,但它仍为当前的打包和分发基础设施奠定了基础,并且不仅仍然是标准库的一部分,而且其名称在其他方面也得以延续(例如用于协调Python打包标准开发的邮件列表的名称)。同样,其他操作系统的软件包很可能会单独提供setuptoolspip,原因如上所述,因为当系统已经有另一个程序包管理器时,它们并不必要,甚至对可维护性有害。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接