5. 创建内置分布

Note

该文档将一直保留,直到https://setuptools.readthedocs.io/en/latest/setuptools.htmlsetuptools文档独立涵盖了此处当前包括的所有相关信息。

您可能习惯将“内置发行版”视为“二进制程序包”或“安装程序”(取决于您的背景)。不过,它不一定是二进制的,因为它可能只包含 Python 源代码和/或字节码;而且我们不称其为包,因为该词已经在 Python 中使用。 (“安装程序”是专用于主流台式机系统的术语.)

内置的发行版是如何使模块发行版的安装程序变得尽可能简单:对于基于 RPM 的 Linux 系统的用户,它是二进制 RPM;它是二进制 RPM。对于 Windows 用户,它是可执行安装程序;对于基于 Debian 的 Linux 用户,这是一个 Debian 软件包。等等。显然,没有人能够在阳光下为每个平台创建构建的发行版,因此 Distutils 旨在使模块开发人员能够专注于他们的专业-编写代码和创建源发行版-而称为* packages * springs 的中间物种可以将源分发版转换为适用于与打包程序一样多的平台的内置分发版。

当然,模块开发人员可以是他们自己的打包程序;或者打包者可以是“在外面”的志愿者,该志愿者可以访问原始开发人员无法访问的平台;也可以是软件定期获取新的源发行版,并将其转变为针对该软件可访问的多个平台的内置发行版。无论他们是谁,打包程序都使用安装脚本和 bdist 命令族来生成内置发行版。

作为一个简单的示例,如果我在 Distutils 源代码树中运行以下命令:

python setup.py bdist

然后 Distutils 构建我的模块分发版(在这种情况下为 Distutils 本身),进行“伪造”安装(也在build目录中),并为我的平台创建默认类型的构建分发版。内置发行版的默认格式是 Unix 上的“哑” tar 文件,而在 Windows 上是简单的可执行安装程序。 (该 tar 文件被视为“哑”文件,因为必须将其解压缩到特定位置才能工作.)

因此,上述命令在 Unix 系统上会创建Distutils-1.0.plat.tar.gz;从正确的位置解压缩此 tarball 将安装 Distutils,就像您已下载源代码发行版并运行python setup.py install一样。 (“正确的位置”是文件系统的根目录或 Python 的prefix目录,具体取决于对 bdist_dumb 命令提供的选项;默认是相对于prefix进行愚蠢的分发.)

显然,对于纯 Python 发行版,这不仅比运行python setup.py install简单,而且对于非纯发行版,其中包括需要编译的扩展,这可能意味着某人能够使用您的扩展与否。即使您的发行版不包含任何 extensions,创建“智能”内置发行版(如 RPM 软件包或 Windows 的可执行安装程序)对于用户来说也更为方便。

bdist 命令具有--formats选项,类似于 sdist 命令,您可以使用它来选择要生成的内置发行版的类型:例如,

python setup.py bdist --format=zip

在 Unix 系统上运行时,将再次创建Distutils-1.0.plat.zip,将从根目录解压缩此存档以安装 Distutils。

内置发行版的可用格式为:

FormatDescriptionNotes
gztar压缩的 tar 文件(.tar.gz)(1)
bztar压缩的 tar 文件(.tar.bz2)
xztar压缩的 tar 文件(.tar.xz)
ztar压缩的 tar 文件(.tar.Z)(3)
tartar 文件(.tar)
zipzipfile(.zip)(2),(4)
rpmRPM(5)
pkgtoolSolaris pkgtool
sduxHP-UX swinstall
wininstWindows 的自解压 ZIP 文件(4)
msiMicrosoft Installer.

在版本 3.5 中进行了更改:添加了对xztar格式的支持。

Notes:

  • 在 Unix 上默认

  • Windows 默认

  • 需要外部 compress Util。

  • 需要外部 zip Util 或zipfile模块(自 Python 1.6 以来为标准 Python 库的一部分)

  • 需要外部 rpm 实用工具(版本 3.0.4 或更高版本)(使用rpm --version来查找您拥有的版本)

您无需在--formats选项中使用 bdist 命令;您还可以使用直接实现您感兴趣的格式的命令。其中一些 bdist “子命令”实际上会生成几种相似的格式;例如, bdist_dumb 命令生成所有“哑”存档格式(targztarbztarxztarztarzip),而 bdist_rpm 生成二进制 RPM 和源 RPM。 bdist 子命令以及每个子命令生成的格式为:

CommandFormats
bdist_dumbtar,gztar,bztar,xztar,ztar,zip
bdist_rpmrpm, srpm
bdist_wininstwininst
bdist_msimsi

Note

从 Python 3.8 开始不推荐使用 bdist_wininst。

以下各节详细介绍了各个 bdist _ *命令。

5.1. 创建 RPM 软件包

RPM 格式被许多流行的 Linux 发行版使用,包括 Red Hat,SuSE 和 Mandrake。如果其中一个(或其他任何基于 RPM 的 Linux 发行版)是您的常规环境,那么为相同发行版的其他用户创建 RPM 包就很简单了。根据模块发行版的复杂性以及 Linux 发行版之间的差异,您也许还可以创建在不同的基于 RPM 的发行版上工作的 RPM。

创建模块分发的 RPM 的通常方法是运行 bdist_rpm 命令:

python setup.py bdist_rpm

或带有--format选项的 bdist 命令:

python setup.py bdist --formats=rpm

前者允许您指定 RPM 特定的选项;后者使您可以一次运行轻松指定多种格式。如果您需要同时执行两项操作,则可以显式指定多个 bdist _ *命令及其选项:

python setup.py bdist_rpm --packager="John Doe <[email protected]>" \
                bdist_wininst --target-version="2.0"

创建 RPM 软件包由.spec文件驱动,就像使用 Distutils 由安装脚本驱动一样。为了使您的生活更轻松, bdist_rpm 命令通常根据您在安装脚本,命令行以及任何 Distutils 配置文件中提供的信息来创建.spec文件。 .spec文件中的各种选项和部分是从安装脚本中的选项派生的,如下所示:

RPM .spec文件选项或部分Distutils 安装脚本选项
Namename
摘要(在序言中)description
Versionversion
Vendorauthorauthor_email,或—&maintainermaintainer_email
Copyrightlicense
Urlurl
%description (section)long_description

此外,.spec文件中有很多选项,而安装脚本中没有相应的选项。其中大多数pass bdist_rpm 命令的选项进行处理,如下所示:

RPM .spec文件选项或部分bdist_rpm 选项default value
Releaserelease"1"
Groupgroup"Development/Libraries"
Vendorvendor(see above)
Packagerpackager(none)
Providesprovides(none)
Requiresrequires(none)
Conflictsconflicts(none)
Obsoletesobsoletes(none)
Distributiondistribution_name(none)
BuildRequiresbuild_requires(none)
Iconicon(none)

显然,在命令行中甚至提供这些选项中的几个都是很乏味且容易出错的,因此通常最好将它们放在安装配置文件setup.cfg中—请参见编写安装程序配置文件。如果您分发或打包许多 Python 模块分发版,则可能需要将适用于所有这些选项的选项放到您的个人 Distutils 配置文件(~/.pydistutils.cfg)中。如果要暂时禁用此文件,可以将--no-user-cfg选项传递给setup.py

构建二进制 RPM 软件包需要执行三个步骤,所有这些步骤都由 Distutils 自动处理:

  • 创建一个用于描述程序包的.spec文件(类似于 Distutils 安装脚本;实际上,安装脚本中的许多信息都出现在.spec文件中)

  • 创建源 RPM

  • 创建“二进制” RPM(可能包含二进制代码,也可能不包含二进制代码,具体取决于您的模块分发版本是否包含 Python 扩展)

通常,RPM 将最后两个步骤 Binding 在一起。当您使用 Distutils 时,通常将所有三个步骤 Binding 在一起。

如果需要,可以将这三个步骤分开。您可以使用--spec-only选项使 bdist_rpm 只需创建.spec文件并退出;在这种情况下,.spec文件将被写入“分发目录”(通常为dist/),但可以pass--dist-dir选项进行自定义。 (通常,.spec文件会在 bdist_rpm 创建的临时目录的“构建树”中深入显示.)

5.2. 创建 Windows 安装程序

Warning

从 Python 3.8 开始不推荐使用 bdist_wininst。

可执行安装程序是 Windows 上二进制发行版的自然格式。它们显示了一个漂亮的图形用户界面,显示了要从安装脚本中的元数据中获取的有关要安装的模块发行版的一些信息,让用户选择了几个选项,然后开始或取消安装。

由于元数据是从安装脚本中获取的,因此创建 Windows 安装程序通常与运行一样容易:

python setup.py bdist_wininst

或带有--formats选项的 bdist 命令:

python setup.py bdist --formats=wininst

如果您具有纯模块发行版(仅包含纯 Python 模块和软件包),则生成的安装程序将与版本无关,并且名称类似于foo-1.0.win32.exe。请注意,仅在 Windows 系统上支持在wininst个二进制发行版中创建。

如果您使用的是非纯发行版,则扩展只能在 Windows 平台上创建,并且取决于 Python 版本。安装程序文件名将反映这一点,现在的格式为foo-1.0.win32-py2.0.exe。您必须为要支持的每个 Python 版本创建一个单独的安装程序。

在正常和优化模式下,在目标系统上安装后,安装程序将try将纯模块编译成bytecode。如果您由于某种原因不希望发生这种情况,可以使用--no-target-compile和/或--no-target-optimize选项运行 bdist_wininst 命令。

默认情况下,安装程序运行时将显示凉爽的“ Python Powered”徽标,但您也可以提供自己的 152x261 位图,该位图必须是带有.bmp选项的 Windows .bmp文件。

运行时,安装程序还将在桌面背景窗口上显示一个大标题,该标题由发行版本的名称和版本号构成。可以使用--title选项将其更改为其他文本。

安装程序文件将被写入“分发目录”(通常为dist/,但可以使用--dist-dir选项进行自定义)。

5.3. 在 Windows 上交叉编译

从 Python 2.6 开始,distutils 能够在 Windows 平台之间交叉编译。实际上,这意味着在安装正确的工具后,您可以使用 32 位版本的 Windows 创建 64 位 extensions,反之亦然。

要为备用平台进行构建,请在 build 命令中指定--plat-name选项。当前有效值为“ win32”和“ win-amd64”。例如,在 Windows 的 32 位版本上,您可以执行:

python setup.py build --plat-name=win-amd64

构建扩展的 64 位版本。 Windows Installers 也支持此选项,因此命令:

python setup.py build --plat-name=win-amd64 bdist_wininst

会在 32 位版本的 Windows 上创建 64 位安装可执行文件。

要交叉编译,必须下载 Python 源代码并针对目标平台交叉编译 Python 本身-不能pass二进制安装 Python(因为不包括其他平台的.lib 等文件)。实际上,这意味着 32 位 os 的用户将需要使用 Visual Studio 2008 在 Python 源代码树中打开PCbuild/PCbuild.sln解决方案并构建“ pythoncore”项目的“ x64”配置,然后才能进行交叉编译扩展。

请注意,默认情况下,Visual Studio 2008 不安装 64 位编译器或工具。您可能需要重新执行 Visual Studio 设置过程并选择这些工具(使用“控制面板”->“添加/删除”程序是检查或修改现有安装的便捷方法.)

5.3.1. 安装后脚本

从 Python 2.3 开始,可以使用--install-script选项指定安装后脚本。必须指定脚本的基本名称,并且脚本文件名也必须在 setup 函数的 scripts 参数中列出。

复制所有文件后,该脚本将在安装时在目标系统上运行,并将argv[1]设置为-install,然后在卸载时再次运行,然后将文件argv[1]设置为-remove删除。

安装脚本嵌入 Windows 安装程序中运行,每个输出(sys.stdoutsys.stderr)都重定向到缓冲区中,并且在脚本完成后将在 GUI 中显示。

在此情况下,一些特别有用的Function可以作为安装脚本中的其他内置Function使用。

  • directory_created(* path *)

  • file_created(* path *)

    • 在安装时由后安装脚本创建目录或文件时,应调用这些函数。它将在卸载程序中注册* path *,以便在卸载发行版时将其删除。为了安全起见,仅在目录为空时才将其删除。
  • get_special_folder_path(* csidl_string *)

    • 此Function可用于在 Windows 上检索特殊文件夹位置,例如“开始”菜单或“桌面”。它返回文件夹的完整路径。 * csidl_string *必须是以下字符串之一:
"CSIDL_APPDATA"

"CSIDL_COMMON_STARTMENU"
"CSIDL_STARTMENU"

"CSIDL_COMMON_DESKTOPDIRECTORY"
"CSIDL_DESKTOPDIRECTORY"

"CSIDL_COMMON_STARTUP"
"CSIDL_STARTUP"

"CSIDL_COMMON_PROGRAMS"
"CSIDL_PROGRAMS"

"CSIDL_FONTS"

如果无法检索该文件夹,则引发OSError

可用的文件夹取决于确切的 Windows 版本,可能还取决于配置。有关详细信息,请参阅 Microsoft 的SHGetSpecialFolderPath()函数文档。

  • create_shortcut((* target description filename * [,* arguments * [,* workdir * [,* iconpath * [,* iconindex *]]]]))
    • 此Function创建快捷方式。 * target *是由快捷方式启动的程序的路径。 * description *是快捷方式的描述。 * filename *是用户将看到的快捷方式的标题。 * arguments *指定命令行参数(如果有)。 * workdir *是程序的工作目录。 * iconpath 是包含快捷方式图标的文件, iconindex 是文件 iconpath *中图标的索引。同样,有关详细信息,请查阅IShellLink界面的 Microsoft 文档。

5.4. Vista 用户访问控制(UAC)

从 Python 2.6 开始,bdist_wininst 支持--user-access-control选项。默认值为“无”(表示未完成 UAC 处理),其他有效值为“自动”(表示为所有用户安装 Python 时提示 UAC 提升)和“强制”(表示始终提示提升)。

Note

从 Python 3.8 开始不推荐使用 bdist_wininst。