MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python虚拟环境与全局环境的区别

2023-06-296.0k 阅读

1. Python 环境概述

在深入探讨 Python 虚拟环境与全局环境的区别之前,我们需要先对 Python 环境有一个基本的认识。Python 环境是 Python 程序运行所需的一系列配置和资源的集合,包括 Python 解释器、安装的各种库以及相关的系统路径等。

Python 解释器是运行 Python 代码的核心组件,它负责将我们编写的 Python 代码转换为计算机能够理解和执行的机器语言。而库则是由其他开发者编写好的代码集合,用于实现各种功能,例如用于数据科学的 numpypandas,用于网络编程的 requests 等。这些库可以极大地提高我们开发的效率,避免重复造轮子。

系统路径则决定了 Python 解释器在查找模块和库时的搜索范围。当我们在代码中使用 import 语句导入一个模块时,Python 解释器会按照系统路径中指定的目录顺序进行查找。如果在这些目录中找不到对应的模块,就会抛出 ImportError 错误。

2. 全局环境

2.1 全局环境的定义与特点

全局环境是系统级别的 Python 环境,当我们在系统上安装 Python 时,就创建了一个全局环境。这个环境对系统中的所有用户和项目都是可见的。

  • 共享性:所有用户都可以使用全局环境中安装的 Python 解释器和库。例如,在 Linux 系统中,多个用户登录到同一台服务器,他们都可以访问全局环境下安装的 Python 相关资源。这在一定程度上方便了系统范围内的 Python 应用部署,比如一些系统级别的脚本可能依赖于全局环境中的特定库。
  • 稳定性要求高:由于全局环境被多个项目和用户共享,对其稳定性有较高要求。如果随意在全局环境中安装、升级或删除库,可能会影响到其他依赖这些库的项目的正常运行。例如,一个系统服务依赖于 Django 2.2 版本,若在全局环境中升级 Django3.0,可能导致该系统服务无法正常工作。

2.2 全局环境的安装与配置

以在 Linux 系统(如 Ubuntu)上安装 Python 为例,通常可以使用系统的包管理器来安装。例如,通过以下命令安装 Python 3:

sudo apt update
sudo apt install python3

安装完成后,Python 解释器会被放置在系统的特定路径下,一般是 /usr/bin/python3。同时,系统会配置好相关的环境变量,使得在任何目录下都可以通过命令行直接调用 python3 来启动解释器。

对于库的安装,在全局环境中,我们通常使用 pip 命令。例如,安装 numpy 库:

sudo pip3 install numpy

这里使用 sudo 是因为全局环境的安装需要管理员权限,以确保库能够正确安装到系统指定的共享目录中。安装后的库文件会被放置在类似于 /usr/local/lib/python3.x/dist-packages 的目录下(x 为具体的 Python 版本号)。

2.3 全局环境的优缺点

  • 优点
    • 方便系统级应用:对于一些系统层面的 Python 脚本或服务,使用全局环境可以方便地利用已安装的库,无需为每个服务单独配置环境。例如,系统的日志管理脚本可能依赖于全局环境中的 logging 库及其相关的配置。
    • 易于管理基础依赖:一些基础的、被广泛使用的库可以在全局环境中统一安装和维护,减少重复安装的开销。比如,setuptoolspip 等工具通常安装在全局环境中,方便所有项目使用。
  • 缺点
    • 版本冲突问题:不同项目可能依赖于同一库的不同版本。例如,项目 A 依赖 Flask 1.1.2,而项目 B 依赖 Flask 2.0.1。在全局环境中很难同时满足这两个项目的需求,因为安装一个版本会覆盖另一个版本,导致其中一个项目无法正常运行。
    • 安全性风险:由于全局环境对所有用户可见,任何用户都可以在全局环境中安装或修改库,这可能带来安全风险。恶意用户可能会修改关键库,影响系统的稳定性和安全性。

3. 虚拟环境

3.1 虚拟环境的定义与原理

虚拟环境是 Python 为每个项目创建的独立的运行环境。它通过在系统中创建一个独立的目录结构,将 Python 解释器、库以及相关的配置都隔离在这个目录中,使得不同项目之间的环境相互独立,互不干扰。 虚拟环境的原理主要基于以下几点:

  • 目录隔离:每个虚拟环境都有自己独立的目录,在这个目录下有独立的 bin(存放可执行文件,如 Python 解释器)、lib(存放安装的库文件)和 include 等目录。例如,创建一个名为 myenv 的虚拟环境,其目录结构大致如下:
myenv/
├── bin/
│   ├── python
│   ├── pip
│   └──...
├── lib/
│   └── python3.x/
│       └── site-packages/
│           └──...
└── include/
    └── python3.x/
        └──...
  • 环境变量修改:当激活一个虚拟环境时,系统的环境变量会被修改,使得 Python 解释器和 pip 命令优先使用虚拟环境目录中的资源。例如,PATH 环境变量会被修改,将虚拟环境的 bin 目录置于系统 PATH 的前面,这样当执行 pythonpip 命令时,实际上调用的是虚拟环境中的相应程序。

3.2 虚拟环境的创建与激活

在 Python 中,创建虚拟环境有多种方式,最常用的是使用内置的 venv 模块(Python 3.3 及以上版本)。以下是在命令行中创建和激活虚拟环境的步骤:

  • 创建虚拟环境:假设我们要创建一个名为 myenv 的虚拟环境,可以使用以下命令:
python3 -m venv myenv

这会在当前目录下创建一个名为 myenv 的虚拟环境目录,其中包含了 Python 解释器的副本以及一个基本的 pip 工具。

  • 激活虚拟环境
    • 在 Windows 系统下,如果是基于 cmd 命令行,对于 myenv 虚拟环境,激活命令如下:
myenv\Scripts\activate.bat

如果是在 PowerShell 中,则使用:

myenv\Scripts\Activate.ps1

(注意,在 PowerShell 中可能需要先通过 Set - ExecutionPolicy - Scope CurrentUser - ExecutionPolicy RemoteSigned 命令改变执行策略,以允许运行脚本)

  • 在 Linux 或 macOS 系统下,激活命令为:
source myenv/bin/activate

激活虚拟环境后,命令行提示符会发生变化,通常会在前面加上虚拟环境的名称,例如 (myenv) user@host:~$,表示当前处于 myenv 虚拟环境中。

3.3 虚拟环境的库安装与管理

在虚拟环境激活的状态下,使用 pip 安装库时,库会被安装到虚拟环境的 lib/python3.x/site - packages 目录中,而不会影响全局环境。例如,在 myenv 虚拟环境中安装 requests 库:

pip install requests

安装完成后,只有在 myenv 虚拟环境中才能使用 requests 库。如果在其他虚拟环境或全局环境中执行 import requests,会提示找不到该模块,除非在相应环境中也安装了 requests

当我们完成项目开发,不再需要虚拟环境中的某些库时,可以使用 pip uninstall 命令卸载。例如,卸载刚才安装的 requests 库:

pip uninstall requests

这样只会卸载 myenv 虚拟环境中的 requests 库,对其他环境没有影响。

3.4 虚拟环境的优点与适用场景

  • 优点
    • 版本隔离:不同项目可以使用同一库的不同版本。例如,项目 A 可以在其虚拟环境中安装 Django 1.11,而项目 B 在其虚拟环境中安装 Django 2.2,两个项目互不干扰,各自可以基于所需的库版本进行开发和运行。
    • 安全性和独立性:虚拟环境为每个项目提供了独立的运行空间,一个项目的环境变化不会影响其他项目。同时,由于虚拟环境的操作不需要管理员权限,降低了安全风险,恶意用户无法通过修改虚拟环境影响其他项目或系统全局。
  • 适用场景
    • 项目开发:在开发多个 Python 项目时,每个项目都应该使用独立的虚拟环境。这样可以确保项目依赖的库版本与其他项目隔离,避免因版本冲突导致的问题。例如,一个数据分析项目可能依赖特定版本的 numpypandas,而一个 Web 开发项目依赖特定版本的 FlaskDjango,使用虚拟环境可以让它们和谐共存。
    • 测试与部署:在进行软件测试和部署时,虚拟环境可以模拟生产环境的依赖。测试人员可以在虚拟环境中安装与生产环境相同版本的库,进行全面的测试。在部署时,将虚拟环境打包部署到服务器上,可以确保服务器上的运行环境与开发和测试环境一致,减少因环境差异导致的部署问题。

4. Python 虚拟环境与全局环境的详细区别

4.1 库的安装位置与共享性

  • 全局环境:库安装在系统级别的共享目录中,如 /usr/local/lib/python3.x/dist - packages(Linux 系统)。所有用户和项目都可以共享这些库。这意味着一旦在全局环境中安装了某个库,所有使用全局环境的项目都可以直接导入和使用它。例如,如果在全局环境中安装了 matplotlib 库,系统中任何使用全局 Python 环境的脚本都可以通过 import matplotlib 来使用该库。
  • 虚拟环境:库安装在虚拟环境自身的 lib/python3.x/site - packages 目录下。每个虚拟环境都有自己独立的库安装位置,不同虚拟环境之间的库是隔离的。例如,在虚拟环境 env1 中安装的 numpy 库,不会在虚拟环境 env2 中自动可用,env2 如果需要 numpy,必须在 env2 中单独安装。

4.2 版本管理与冲突解决

  • 全局环境:由于所有项目共享全局环境中的库,版本管理变得困难。如果一个项目需要特定版本的库,而其他项目依赖该库的不同版本,就会产生版本冲突。例如,项目 A 依赖 scikit - learn 0.23,项目 B 依赖 scikit - learn 0.24,在全局环境中很难同时满足这两个项目的需求,升级或降级 scikit - learn 可能导致其中一个项目无法正常运行。
  • 虚拟环境:每个虚拟环境可以独立管理库的版本。不同虚拟环境可以安装同一库的不同版本,互不影响。例如,在虚拟环境 project_a_env 中可以安装 scikit - learn 0.23,而在虚拟环境 project_b_env 中安装 scikit - learn 0.24,这样两个项目都能基于各自所需的库版本正常运行,有效地解决了版本冲突问题。

4.3 环境变量与路径设置

  • 全局环境:使用系统级别的环境变量和路径设置。Python 解释器和库的搜索路径是系统默认配置的,一般是系统路径下的特定目录。例如,在 Linux 系统中,Python 解释器的默认路径是 /usr/bin/python3,库的搜索路径包括 /usr/local/lib/python3.x/dist - packages 等。当我们在全局环境中执行 python 命令时,系统会按照这些默认路径查找解释器和相关库。
  • 虚拟环境:当激活虚拟环境时,环境变量会被修改。PATH 环境变量会将虚拟环境的 bin 目录置于系统 PATH 的前面,使得 pythonpip 命令优先使用虚拟环境中的解释器和工具。同时,Python 的库搜索路径也会被修改为虚拟环境的 lib/python3.x/site - packages 目录。例如,激活虚拟环境 myenv 后,执行 python 命令实际上是调用 myenv/bin/python,导入库时会首先在 myenv/lib/python3.x/site - packages 目录中查找。

4.4 用户权限与安全性

  • 全局环境:在全局环境中安装、升级或删除库通常需要管理员权限(如在 Linux 系统中使用 sudo 命令)。这是因为全局环境的修改会影响系统中所有用户和项目。然而,这也带来了一定的安全风险,如果恶意用户获取了管理员权限,就可以随意修改全局环境中的库,可能导致系统不稳定或数据泄露等问题。
  • 虚拟环境:创建、激活和管理虚拟环境以及在虚拟环境中安装库不需要管理员权限,普通用户即可操作。每个用户可以在自己的用户目录下创建和管理虚拟环境,这提高了安全性。即使某个虚拟环境被恶意修改,也只会影响该虚拟环境对应的项目,不会对其他项目或系统全局造成影响。

4.5 项目适用性与灵活性

  • 全局环境:适用于一些系统级别的 Python 应用或脚本,这些应用通常依赖于一些基础的、稳定的库,并且对所有用户都是共享的。例如,系统的定时任务脚本可能依赖于全局环境中的 schedule 库来实现定时功能。但对于多个不同需求的项目开发,全局环境的灵活性较差,因为很难满足各个项目对库版本等的不同要求。
  • 虚拟环境:非常适合项目开发和测试场景。每个项目可以根据自身需求创建独立的虚拟环境,在虚拟环境中安装特定版本的库,进行项目的开发、测试和部署。虚拟环境的灵活性使得项目之间可以保持高度的独立性,开发者可以根据项目的进展和需求随时调整虚拟环境中的库版本和配置,而不会影响其他项目。

5. 代码示例演示区别

5.1 全局环境代码示例

首先,确保在全局环境中安装了 numpy 库(假设已经安装)。创建一个名为 global_env_demo.py 的文件,内容如下:

import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(np.mean(arr))

在命令行中直接运行该脚本(假设全局环境的 Python 解释器在系统路径中):

python global_env_demo.py

该脚本会顺利运行并输出数组的平均值,因为全局环境中安装了 numpy 库,Python 解释器能够找到并导入该库。

5.2 虚拟环境代码示例

  • 创建并激活虚拟环境
python3 -m venv my_virtual_env
source my_virtual_env/bin/activate
  • 在虚拟环境中安装库:在激活的虚拟环境中安装 numpy 库:
pip install numpy
  • 编写代码:创建一个名为 virtual_env_demo.py 的文件,内容如下:
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(np.mean(arr))
  • 运行代码:在激活的虚拟环境命令行中运行该脚本:
python virtual_env_demo.py

该脚本同样会输出数组的平均值。但如果此时在未激活虚拟环境的情况下,在全局环境命令行中运行 python virtual_env_demo.py,会报错 ModuleNotFoundError: No module named 'numpy',因为全局环境中可能没有安装 numpy 库,或者即使安装了,虚拟环境中的 numpy 库与全局环境相互隔离。

通过这个简单的代码示例,可以清晰地看到虚拟环境与全局环境在库的使用和隔离方面的区别。虚拟环境使得每个项目可以独立管理自己的依赖库,避免了与其他项目的冲突,而全局环境则更侧重于系统范围内的共享使用,但在处理多项目依赖差异时存在局限性。

6. 选择虚拟环境还是全局环境

在实际开发中,选择使用虚拟环境还是全局环境取决于具体的应用场景和需求。

  • 项目开发场景:对于大多数项目开发,强烈推荐使用虚拟环境。每个项目都有其独特的依赖库和版本需求,虚拟环境能够确保项目之间的独立性,避免版本冲突等问题。例如,在开发一个基于 Flask 的 Web 应用和一个基于 PyTorch 的深度学习项目时,使用虚拟环境可以让两个项目分别安装各自所需版本的 FlaskPyTorch,互不干扰。
  • 系统级脚本或服务:如果是编写一些系统级别的脚本或服务,这些脚本或服务依赖于一些基础的、稳定的库,并且对整个系统的所有用户都适用,那么可以考虑使用全局环境。例如,系统的备份脚本可能依赖于全局环境中的 paramiko 库来实现远程文件传输,因为这个脚本通常不需要频繁更改库的版本,并且对系统中的所有用户都应该是可用的。
  • 学习与实验:在学习 Python 新库或者进行一些简单的实验时,可以使用全局环境,因为这样可以快速安装和使用库,不需要每次都创建和激活虚拟环境。但随着学习的深入和项目规模的扩大,还是建议逐渐过渡到使用虚拟环境,以培养良好的开发习惯和避免潜在的环境问题。

总之,虚拟环境在现代 Python 开发中扮演着至关重要的角色,它为项目的开发、测试和部署提供了更加灵活和可靠的环境。而全局环境在一些特定的系统级应用场景中仍然有其存在的价值。开发者需要根据具体情况,合理选择和使用这两种环境,以提高开发效率和项目的稳定性。