在 Windows 上使用内置 python 构建软件安装程序

Building software installer with built-in python on Windows

我们的命令行实用程序是用 Python 编写的。

在 Linux/OS X 上这通常不是问题,因为两者都预装了 Python 2.x。但是在 Windows 上,Python 没有默认安装。

另一个问题是我们的依赖项很少需要编译,这对于 Windows 用户来说又不是一个小问题,因为它需要修补 MSVC/Cygwin/etc'。

到目前为止,我们通过使用 Pyinstaller 创建具有预安装依赖项的 "frozen" Python 包解决了这个问题。这工作得很好,但是使我们的实用程序不可扩展 - 我们不能通过使用诸如 pip 之类的实用程序来添加额外的 Python 模块。由于我们的 CLI 依赖于此功能以增加额外的可用性,因此此限制成为我们的障碍,我们想重新考虑我们的方法。

四处寻找,我发现了 Rhodecode solve this。基本上他们的安装程序带来 Python 和其他一切(包括预编译的依赖项)。

这对我们来说似乎是个好主意,我在这里看到的唯一限制是他们的安装程序实际上是从 .msi 安装 Python,这将内容放入 Windows 注册表。所以在 Windows 上只能安装一个 Python 版本 X.Y(来自 .msi

对于服务器应用程序,这可能是合理的,因为服务器应用程序往往表现得好像它是 PC 上唯一安装的东西,但对于命令行实用程序,这是完全不能接受的。

环顾四周,我发现很少有项目声称 Python 可移植 - 例如 Portable Python. However I'm not sure how "portable" it really is, especially after issues like this.

所以问题是:

  1. 是否可以在 Windows 上多次安装相同的 Python 版本而不会在实例之间造成冲突?

  2. 你会选择其他解决方法来解决这个问题吗(请不要 "smart" 解决方案,例如:放弃 Windows support/don 不要使用 Python )

谢谢!

坦率地说,我会坚持使用 PyInstaller 或类似的东西。这将始终为您提供 Python 的正确版本,无论目标机器是否安装了 Python。它还可以防止您破坏以前安装的 Python.

版本

如果您需要添加插件,则应将其构建到您的应用中。有一些项目可以帮助您。这里有几个例子:

您也可以看看 Django 或 Flask 是如何处理扩展的。例如,您可以向 Flask 添加扩展以允许它与 SQLAlchemy. You should be able to do something similar with your own application. The pip utility won't work with a frozen application after all. Alternatively, have you looked at conda?它可能适合您的目的。

这是我第二个问题的答案,遗憾的是我还没有找到更好的解决方案 1。

目前我们改变了创建安装文件的方法:

  1. 我们将我们的代码及其依赖项打包为一组预构建的 Python 轮子。自 Visual C++ compiler for Python2.7.
  2. 发布以来,在 Windows 上创建预制轮子相对容易
  3. 我们将 Python setup MSI 与 Pip、Setuptools 和 Virtualenv wheels 打包在一起。
  4. 在安装开始之前,我们检查 Python、Pip 和 Virtualenv 是否已经安装(通过查看注册表和 \Scripts),如果没有,我们从打包的 wheels 中安装它。 Pip wheel 是通过使用我们捆绑的 get-pip.py 脚本安装的。
  5. 我们创建单独的 Virtualenv 并将轮子安装到其中。
  6. 通过删除 virtualenv 文件夹完成卸载。 Python,Pip 和 Virtualenv 安装被遗忘。

Inno Setup 创建的安装程序。

我仍然对这个解决方案不完全满意,因为一些组件是全局安装的,可能会与用户之前安装的组件冲突(older/newer 版本的 python、pip、setuptools 或 virtualenv ).这会在安装或运行时产生不可预知的错误。或者用户将来升级其中一个组件并以某种方式破坏应用程序的可能性。

此外,卸载很脏,会留下一些东西。