setuptools与distutils:为什么distutils仍然是一回事?

问题:setuptools与distutils:为什么distutils仍然是一回事?

Python就可以用于包装和说明项目工具混淆历史:这些包括distutils标准库中,distributedistutils2,和setuptools(也许更多)。看来,distributedistutils2投票赞成的停产setuptools,这让两个相互竞争的标准。

据我所知,setuptools提供了更多的选择(例如,声明依赖项,测试等)distutils,但是它没有包含在Python标准库中(还可以吗?)。

现在推荐《Python打包用户指南》 [ 1 ]:

使用setuptools定义的项目和创建源代码分发。

并说明:

尽管您可以将pure distutils用于许多项目,但它不支持定义对其他项目的依赖关系,并且缺少一些便捷实用程序来自动正确填充所提供的包元数据setuptools。在标准库之外,setuptools还为不同版本的Python提供了更一致的功能集,并且(与不同distutilssetuptools将进行更新,以在所有受支持的版本上生成即将到来的“ Metadata 2.0”标准格式。

即使对于确实选择使用的项目distutils,当pip直接从源代码(而不是从预构建的wheel文件安装)安装此类项目时,它实际上也会使用setuptools来构建您的项目。

但是,查看各种项目的setup.py文件可以发现,这似乎并不是一个实际的标准。许多软件包仍在使用,distutils而那些支持的软件包则setuptools经常setuptoolsdistutils回退导入结合使用:

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

然后尝试找到一种写可以由setuptools和安装的安装程序的方法distutils。由于distutils不支持设置功能中的依赖关系,因此通常包括各种容易出错的依赖关系检查方式。

人们为什么还要付出额外的努力来支持distutilssetuptools标准库中没有的事实是唯一的原因吗?distutils编写仅支持setup.py文件的优点和缺点是什么setuptools

Python has a confusing history of tools that can be used to package and describe projects: these include distutils in the Standard Library, distribute, distutils2, and setuptools (and maybe more). It appears that distribute and distutils2 were discontinued in favor of setuptools, which leaves two competing standards.

To my understanding setuptools offers far more options (e.g. declaring dependencies, tests, etc.) than distutils, however it is not included in the Python standard library (yet?).

The Python Packaging User Guide[1] recommends now:

Use setuptools to define projects and create Source Distributions.

And explains:

Although you can use pure distutils for many projects, it does not support defining dependencies on other projects and is missing several convenience utilities for automatically populating package metadata correctly that are provided by setuptools. Being outside the standard library, setuptools also offers a more consistent feature set across different versions of Python, and (unlike distutils), setuptools will be updated to produce the upcoming “Metadata 2.0” standard formats on all supported versions.

Even for projects that do choose to use distutils, when pip installs such projects directly from source (rather than installing from a prebuilt wheel file), it will actually build your project using setuptools instead.

However, looking into various project’s setup.py files reveals that this does not seem to be an actual standard. Many packages still use distutils and those that support setuptools often mix setuptools with distutils e.g. by doing a fallback import:

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

Followed by an attempt to find a way to write a setup that can be installed by both setuptools and distutils. This often includes various ways of error-prone dependency checking, since distutils does not support dependencies in the setup function.

Why are people still making the extra effort to support distutils – is the fact that setuptools is not in the standard library the only reason? What are the advantages of distutils and are there any drawbacks of writing setup.py files that only support setuptools.


回答 0

看看这个SO问题。它很好地解释了所有打包方法,并可能在某种程度上帮助您回答问题:distribute,distutils,setuptools和distutils2之间的区别?

Distutils仍然是使用Python打包的标准工具。它包含在标准库中(Python 2和Python 3.0至3.3)。它对简单的Python发行版很有用,但缺少功能。它介绍了可以在setup.py脚本中导入的distutils Python软件包。

Setuptools是为克服Distutils的限制而开发的,未包含在标准库中。它引入了一个名为easy_install的命令行实用程序。它还介绍了可以在setup.py脚本中导入的setuptools Python软件包,以及可以在您的代码中导入以查找随发行版一起安装的数据文件的pkg_resources Python软件包。它的陷阱之一是它对distutils Python软件包进行了Monkey修补。它应该与pip配合良好。最新版本于2013年7月发布。

因此,正如您所见,setuptools应该比distutils更受青睐,而且我知道您的问题是从哪里来的,但是我看不到distutils会很快失去支持,因为简单地说,它在许多情况下都与一些流行的旧版程序一起使用。 。正如您可能知道的那样,在旧版程序中更改此类操作可能会很痛苦,并且会遇到很多问题,例如不兼容,这将导致开发人员不得不重写源代码。因此,distutils是标准python库的一部分,而setuptools不是。因此,如果您现在正在创建python程序,请使用setuptools,但是请记住,如果没有distutils,setuptools将永远不存在。

Have a look at this SO question. It explains all the packaging methods very well, and might help answer your question to some extent: Differences between distribute, distutils, setuptools and distutils2?

Distutils is still the standard tool for packaging in Python. It is included in the standard library (Python 2 and Python 3.0 to 3.3). It is useful for simple Python distributions, but lacks features. It introduces the distutils Python package that can be imported in your setup.py script.

Setuptools was developed to overcome Distutils’ limitations, and is not included in the standard library. It introduced a command-line utility called easy_install. It also introduced the setuptools Python package that can be imported in your setup.py script, and the pkg_resources Python package that can be imported in your code to locate data files installed with a distribution. One of its gotchas is that it monkey-patches the distutils Python package. It should work well with pip. The latest version was released in July 2013.

So, as you can see setuptools should be preferred to distutils, and I see where your question comes from, however I don’t see distutils losing support anytime soon, as, simply put, it is used in many cases with some popular legacy programs. And as you probably know changing these sorts of things in legacy programs can be quite a pain and come with quite a few problems, for example incompatibilities, which would then lead to the developer having to rewrite the source code. So there is that, and also the fact that distutils is a part of the standard python library whereas setuptools is not. So, if you are creating a python program, in this day and age, use setuptools, however keep in mind that without distutils, setuptools would have never existed.


回答 1

事实是setuptools不在标准库中的唯一原因

那是原因之一。以下直接来自NumPysetup.py

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才这样做,直到在某些情况下被修补为更喜欢它为止distutils。引用提交日志:

Setuptools sets mode +x on the test scripts, so that Nose refuses to run
them. Better not do that.

当然,一个合并之间setuptoolsdistribute应该解决这一切在适当的时间,但许多软件包仍然需要支持的Python 2.6的安装。

is the fact that setuptools is not in the standard library the only reason

That’s one reason. The following is straight from the NumPy setup.py:

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

So NumPy prefers setuptools if it can find it. But then SciPy used to do this, until it was patched to prefer distutils in some situations. Citing the commit log:

Setuptools sets mode +x on the test scripts, so that Nose refuses to run
them. Better not do that.

Of course, a merger between setuptools and distribute should resolve all this in due time, but many packages still need to support Python 2.6 installations.


回答 2

尽管setuptools无疑是更好的工具集,但仍有许多原因值得我们讨论和使用distutils。

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

其次,setuptools提供了对distutils的增强。因此,它是根据distutils工具集建模的,并从那里开始获取其所有结构。setuptools的文档假定读者熟悉distutils,并且仅记录其如何增强基本工具集。您可以想到distutils定义了方言,而setuptools增强了该方言。

我对新项目的个人方法是从我将要使用distutils的假设开始的。只有随着项目的增长需要设置工具的功能,我才进行升级。setuptools是distutils的替代品,它是对setup.py的单行更改。

There are several reasons we still talk about and use distutils, even though setuptools is without a doubt the better tool set.

Firstly, distutils is available everywhere. If you are looking to build a module for sharing with others, and don’t have any complicated requirements, it is guaranteed to be available on your work machine. This is particularly important if you have to support older versions of python, or if you find yourself working in an unfamiliar environment.

Secondly, setuptools provides enhancements to distutils. It is therefore modeled after the distutils tool set and takes all of it’s structure from there. The documentation for setuptools assumes the reader is familiar with distutils and only documents how it enhances the base tool set. You can think of it that distutils defines the dialect and setuptools enhances that dialect.

My personal approach for new projects is start with the assumption I’m going to use distutils. Only as the project grows to require a feature of setuptools do I make the upgrade. The setuptools is a drop-in-replacement for distutils, it’s a one-line change to my setup.py.


回答 3

基本上,这是由于职责划分。

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

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

有效地,核心团队缩小了distutils的范围,自己保留了“核心标准”和“最小必要编译”部分,同时将超出此范围的所有东西(扩展的编译器/软件包格式/任何支持)留给了第三方。为了向后兼容,以前覆盖那些“扩展部分”的代码已过时

来自分发Python模块-Python 2.7.12文档

尽管distutils逐步淘汰了直接使用,但它仍为当前的包装和分发基础架构奠定了基础,它不仅仍然是标准库的一部分,而且其名称还可以通过其他方式(例如邮件列表的名称)保留下来。用于协调Python打包标准的开发)。

对于其他操作系统软件包同样可能提供setuptoolspip单独-由于上述原因

  • 并且因为在系统上已经存在另一个软件包管理器时,它们不是必需的-甚至对可维护性有害。

Basically, it’s due to the division of responsibilities.

setuptools is not a part of Python standard library because it’s maintained by a 3rd party rather than Python core team. Which means, among other things:

  • it isn’t covered by the core test suite and isn’t relied upon by core functionality
  • it doesn’t itself set core standards for add-on modules (their location, means of import, C extensions’ binary interface etc.).
  • it’s updated and released independently from Python releases

Effectively, the core team has narrowed down the scope of distutils, reserving the “core standards” and “minimal necessary compilation” parts for themselves while leaving all the stuff beyond that (extended compiler/package format/whatever support) to 3rd parties. The code that was previously covering those “extended parts” was left stale for backwards compatibility.

From Distributing Python Modules — Python 2.7.12 documentation:

While direct use of distutils is being phased out, it still laid the foundation for the current packaging and distribution infrastructure, and it not only remains part of the standard library, but its name lives on in other ways (such as the name of the mailing list used to coordinate Python packaging standards development).

Packages for other OSes are likewise likely to provide setuptools and pip separately – for the aforementioned reasons

  • and because they aren’t necessary – or are even detrimental for maintainability – when there’s already another package manager on the system.