删除系统 Python 时虚拟环境的后果 and/or 已更新

Consequences for virtual env when system's Python is removed and/or updated

为清楚起见进行编辑: 这个问题参考了 venv, which is often confused with virtualenv

删除系统的 Python 安装有什么后果,该安装是使用 venv 在系统上创建虚拟环境的来源?

最终,我要做的是删除 3.7 安装并在发布时安装 3.8,但我不确定虚拟环境与系统环境的联系有多紧密。

提出此问题时可能相关的一些系统详细信息:

鉴于上述详细信息,我的印象是 Python 3.8 将安装到 /usr/local/bin/python3.8,然后 python3 将指向该版本。

虚拟环境是否足以成为一个稳定的 3.7 环境?还是它会崩溃,试图引用不再存在的系统安装?

tl;博士: 所有那些从 Python 来源创建的虚拟环境会发生什么变化?

A​​ virtualenv 包含 python 二进制文件本身的副本,因此应该不会发生任何事情。查看更详细的解释here

virtualenv solves this problem by creating a completely isolated virtual environment for each of your programs. An environment is simply a directory that contains a complete copy of everything needed to run a Python program, including a copy of the python binary itself, a copy of the entire Python standard library, a copy of the pip installer, and (crucially) a copy of the site-packages directory mentioned above. When you install a package from PyPI using the copy of pip that's created by the virtualenv tool, it will install the package into the site-packages directory inside the virtualenv directory. You can then use it in your program just as before.

编辑(占venv vs virtualenv):根据venv-documentation,它可以复制或符号链接二进制文件:

The venv module provides support for creating lightweight “virtual environments” with their own site directories, optionally isolated from system site directories. Each virtual environment has its own Python binary (which matches the version of the binary that was used to create this environment) and can have its own independent set of installed Python packages in its site directories.

坏消息:您正在使用 venv,并且 venv 虚拟环境并非完全独立。即使使用 --copies 创建,它复制的只是 python 可执行文件本身,而不是标准库,甚至(如果您的安装创建共享 libpython 而不是静态库)libpython;它依赖于系统副本。如果 Python 所基于的安装消失,虚拟环境将中断。 它如何 破坏将根据它的创建方式而有所不同。例如,如果您使用以下方法创建它:

python3 -mvenv path/to/venv

python3 表示 Python 3.7,然后将 python3 替换为 Python 3.8,然后您可以修复新版本的虚拟环境:

python3 -mvenv --upgrade path/to/venv

但是您安装的第三方软件包将(有效地)消失(它们将在 path/to/venv/lib/python3.7 中,但 Python 3.8 只会在 path/to/venv/lib/python3.8 中查找),所以您必须重新安装它们。

如果您创建了虚拟环境:

python3.7 -mvenv path/to/venv

然后它就完全坏了(至少如文档所述),the --upgrade switch 仅在 Python 就地升级时才被记录用于升级;由于新 Python 不会被命名为 python3.7,因此您无法就地升级。也就是说,--upgrade 实际上只在升级微版本(从 3.7.1 到 3.7.2 等)时有效,由于前面提到的每个次要版本 lib/pythonX.Y 目录,所以无论哪种方式,你最好从头开始创建一个新的虚拟环境。

需要说明的是,the third party virtualenv package 没有此限制 当且仅当 系统 Python 安装静态链接 libpython。奇怪的是,虽然 --always-copy 标志会让它复制主二进制文件和标准库模块,但它不会导致 libpython 本身(解释器核心)被复制,所以如果主二进制文件依赖于libpython.so 的系统副本,然后删除系统副本会破坏虚拟环境。 如果你确实使用了--always-copy你的python静态链接的可执行文件libpython.aldd /path/to/python3应该不显示 libpython 依赖),那么是的,virtualenv 使重量级更高(在 3.6 的本地测试中,通过适当的开关强制复制,新创建的 venv 环境约为 11 MB,而 virtualenv 环境约为 48 MB;可悲的是,我的 python 动态链接 libpython.so,所以它仍然无法工作)虚拟环境应该在删除系统安装的 Python.

无论如何,最好保留 Python 3.7 安装,只升级到 3.8 而不要删除 3.7(你真的很难接受几十 MB 的磁盘 space?)。即使您将 python3 替换为新的 3.8 安装,python3.7libpython3.7m.so.1.0 等,3.7 标准库的其余部分将继续存在以供虚拟环境依赖;在最坏的情况下,您可能需要手动更改虚拟环境中的符号链接以指向 /path/to/python3.7 而不是 /path/to/python3 以继续使用旧版本(包括所有已安装的第三方软件包)。

尝试保持旧虚拟环境正常工作的另一种方法是备份该虚拟环境的安装状态,删除它,安装新的 Python,创建一个新的虚拟环境,然后使用备份状态以在升级后的虚拟环境中重新安装所有软件包。一个例子可能是:

$ source ~/path/to/venv/bin/activate
$ pip freeze > installed_libs.txt
$ deactivate
$ rm -rf ~/path/to/venv
$ ... install new Python/remove old Python ...
$ python3 -mvenv ~/path/to/venv
$ pip install -r installed_libs.txt  # Optionally add --upgrade to install latest, not fixed versions