跳至内容

虚拟环境

在 Python 项目中工作时,您可能应该使用 **虚拟环境**(或类似机制)来隔离为每个项目安装的包。

信息

如果您已经了解虚拟环境,如何创建和使用它们,您可能希望跳过本节。🤓

提示

**虚拟环境** 不同于 **环境变量**。

**环境变量** 是系统中的一个变量,程序可以使用它。

**虚拟环境** 是一个包含一些文件的目录。

信息

本页将教您如何使用 **虚拟环境** 以及它们的工作原理。

如果您准备好采用 **管理所有内容的工具**(包括安装 Python),请尝试使用 uv

创建项目

首先,为您的项目创建一个目录。

我通常的做法是在我的主目录/用户目录中创建一个名为 code 的目录。

然后,我在里面为每个项目创建一个目录。

// Go to the home directory
$ cd
// Create a directory for all your code projects
$ mkdir code
// Enter into that code directory
$ cd code
// Create a directory for this project
$ mkdir awesome-project
// Enter into that project directory
$ cd awesome-project

创建虚拟环境

首次开始处理 Python 项目时,**在项目中** 创建一个虚拟环境 **里面**。

提示

您只需要在 **每个项目** 上执行一次,而不是每次工作时都执行。

要创建虚拟环境,您可以使用 Python 附带的 venv 模块。

$ python -m venv .venv
该命令的含义
  • python: 使用名为 python 的程序
  • -m: 将模块作为脚本调用,我们将在下一步中告诉它哪个模块
  • venv: 使用名为 venv 的模块,该模块通常随 Python 一起安装
  • .venv: 在新目录 .venv 中创建虚拟环境

如果您安装了 uv,您可以使用它来创建虚拟环境。

$ uv venv

提示

默认情况下,uv 会在名为 .venv 的目录中创建虚拟环境。

但是您可以通过传递一个包含目录名称的附加参数来对其进行自定义。

该命令在名为 .venv 的目录中创建了一个新的虚拟环境。

.venv 或其他名称

您可以在不同的目录中创建虚拟环境,但有一个约定将其称为 .venv

激活虚拟环境

激活新的虚拟环境,以便您运行的任何 Python 命令或安装的任何软件包都使用它。

提示

每次开始新的终端会话以处理项目时都执行此操作。

$ source .venv/bin/activate
$ .venv\Scripts\Activate.ps1

或者,如果您使用 Bash for Windows(例如 Git Bash

$ source .venv/Scripts/activate

提示

每次在该环境中安装新的软件包时,都要重新激活该环境。

这确保了如果您使用该软件包安装的终端(CLI 程序),您使用的是虚拟环境中的程序,而不是可能全局安装的任何其他程序,这些程序可能具有与您需要的版本不同的版本。

检查虚拟环境是否处于活动状态

检查虚拟环境是否处于活动状态(之前的命令已成功执行)。

提示

这是可选的,但它是检查一切正常运行且您正在使用预期的虚拟环境的一种好方法。

$ which python

/home/user/code/awesome-project/.venv/bin/python

如果它显示python二进制文件位于项目(在本例中为awesome-project)内的.venv/bin/python处,则表示操作成功。🎉

$ Get-Command python

C:\Users\user\code\awesome-project\.venv\Scripts\python

如果它显示python二进制文件位于项目(在本例中为awesome-project)内的.venv\Scripts\python处,则表示操作成功。🎉

升级pip

提示

如果您使用 uv 来安装东西而不是pip,那么您不需要升级pip。😎

如果您使用pip来安装软件包(它默认随 Python 一起提供),则应将其升级到最新版本。

安装软件包时出现的许多奇特错误只需先升级pip就能解决。

提示

您通常只需在创建虚拟环境后执行一次此操作。

确保虚拟环境处于活动状态(使用上面的命令),然后运行

$ python -m pip install --upgrade pip

---> 100%

添加.gitignore

如果您使用Git(您应该使用),请添加一个.gitignore文件以将.venv中的所有内容从 Git 中排除。

提示

如果您使用 uv 来创建虚拟环境,那么它已经为您完成了此操作,您可以跳过此步骤。😎

提示

您只需在创建虚拟环境后执行一次此操作。

$ echo "*" > .venv/.gitignore
该命令的含义
  • echo "*":将在终端中“打印”文本*(下一部分会稍微改变这一点)
  • >:左侧命令>打印到终端的任何内容都不应该打印,而是写入右侧的相应文件。
  • .gitignore:应写入文本的文件名称

对于 Git,* 表示“所有内容”。因此,它将忽略.venv目录中的所有内容。

该命令将创建一个包含以下内容的.gitignore文件:

*

安装软件包

激活环境后,您可以在其中安装软件包。

提示

在安装或升级项目所需的软件包时,您只需执行一次此操作。

如果您需要升级版本或添加新的软件包,您需要再次执行此操作

直接安装软件包

如果您时间紧迫,不想使用文件来声明项目的软件包要求,则可以直接安装它们。

提示

将程序所需的软件包和版本放在一个文件中(例如requirements.txtpyproject.toml)是一个(非常)好主意。

$ pip install "fastapi[standard]"

---> 100%

如果您有 uv

$ uv pip install "fastapi[standard]"
---> 100%

requirements.txt安装

如果您有requirements.txt,现在可以使用它来安装其中的软件包。

$ pip install -r requirements.txt
---> 100%

如果您有 uv

$ uv pip install -r requirements.txt
---> 100%
requirements.txt

一个包含一些软件包的requirements.txt可能看起来像这样

fastapi[standard]==0.113.0
pydantic==2.8.0

运行您的程序

激活虚拟环境后,您可以运行您的程序,它将使用虚拟环境中的 Python 及您在那里安装的软件包。

$ python main.py

Hello World

配置您的编辑器

您可能使用编辑器,请确保将其配置为使用您创建的相同虚拟环境(它可能会自动检测到它),以便您获得自动完成和内联错误。

例如

提示

您通常只需在创建虚拟环境时执行一次此操作。

停用虚拟环境

完成项目工作后,您可以停用虚拟环境。

$ deactivate

这样,当您运行python时,它将不会尝试从该虚拟环境中运行它以及那里安装的软件包。

准备工作

现在您已准备好开始处理您的项目。

提示

您想了解上面的所有内容吗?

继续阅读。👇🤓

为什么使用虚拟环境

要使用 FastAPI,您需要安装 Python

之后,您需要安装 FastAPI 和您想要使用的任何其他软件包

要安装软件包,您通常会使用 Python 自带的pip命令(或类似的替代方案)。

但是,如果您直接使用pip,则软件包将安装在您的全局 Python 环境(Python 的全局安装)中。

问题

那么,在全局 Python 环境中安装软件包的问题是什么?

在某些时候,您可能会最终编写许多不同的程序,这些程序依赖于不同的软件包。而您处理的这些项目中的一些将依赖于同一个软件包的不同版本。😱

例如,您可以创建一个名为philosophers-stone的项目,该程序依赖于另一个名为harry的软件包,使用版本1。因此,您需要安装harry

flowchart LR
    stone(philosophers-stone) -->|requires| harry-1[harry v1]

然后,在某个时候,您创建了另一个名为prisoner-of-azkaban的项目,该项目也依赖于harry,但该项目需要harry版本3

flowchart LR
    azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3]

但现在问题是,如果您在全局环境中而不是在本地虚拟环境中安装软件包,您将不得不选择要安装哪个版本的harry

如果您想运行philosophers-stone,您需要先安装harry版本1,例如使用

$ pip install "harry==1"

然后您将在全局 Python 环境中安装harry版本1

flowchart LR
    subgraph global[global env]
        harry-1[harry v1]
    end
    subgraph stone-project[philosophers-stone project]
        stone(philosophers-stone) -->|requires| harry-1
    end

但如果您要运行prisoner-of-azkaban,您需要卸载harry版本1并安装harry版本3(或者只是安装版本3会自动卸载版本1)。

$ pip install "harry==3"

然后您将在全局 Python 环境中安装harry版本3

如果您尝试再次运行philosophers-stone,它很可能无法正常工作,因为它需要harry版本1

flowchart LR
    subgraph global[global env]
        harry-1[<strike>harry v1</strike>]
        style harry-1 fill:#ccc,stroke-dasharray: 5 5
        harry-3[harry v3]
    end
    subgraph stone-project[philosophers-stone project]
        stone(philosophers-stone) -.-x|⛔️| harry-1
    end
    subgraph azkaban-project[prisoner-of-azkaban project]
        azkaban(prisoner-of-azkaban) --> |requires| harry-3
    end

提示

在 Python 软件包中,通常会尽力避免在新版本中出现重大更改,但最好确保安全,并在您能够运行测试以检查一切正常运行时有意识地安装较新版本。

现在,想象一下,您所有的项目都依赖的许多其他软件包。这非常难以管理。您很可能会最终使用软件包的一些不兼容版本来运行一些项目,并且不知道为什么某些东西无法正常工作。

此外,根据您的操作系统(例如 Linux、Windows、macOS),它可能已经预装了 Python。在这种情况下,它可能预装了一些系统需要的特定版本的软件包。如果您在全局 Python 环境中安装软件包,您可能会最终破坏与操作系统一起提供的某些程序。

软件包安装在哪里

安装 Python 时,它会在您的计算机上创建一些包含一些文件的目录。

其中一些目录负责包含您安装的所有软件包。

当您运行

// Don't run this now, it's just an example 🤓
$ pip install "fastapi[standard]"
---> 100%

这将从 PyPI 下载包含 FastAPI 代码的压缩文件。

它还会下载 FastAPI 依赖的其他软件包的文件。

然后,它将提取所有这些文件并将它们放在您计算机上的一个目录中。

默认情况下,它会将下载并提取的文件放在 Python 安装目录中,即全局环境

什么是虚拟环境

将所有软件包放在全局环境中的问题的解决方案是为每个处理的项目使用虚拟环境

虚拟环境是一个目录,与全局目录非常类似,您可以在其中安装项目的软件包。

这样,每个项目都将拥有自己的虚拟环境(.venv目录),包含自己的软件包。

flowchart TB
    subgraph stone-project[philosophers-stone project]
        stone(philosophers-stone) --->|requires| harry-1
        subgraph venv1[.venv]
            harry-1[harry v1]
        end
    end
    subgraph azkaban-project[prisoner-of-azkaban project]
        azkaban(prisoner-of-azkaban) --->|requires| harry-3
        subgraph venv2[.venv]
            harry-3[harry v3]
        end
    end
    stone-project ~~~ azkaban-project

激活虚拟环境意味着什么

当您激活虚拟环境时,例如使用

$ source .venv/bin/activate
$ .venv\Scripts\Activate.ps1

或者,如果您使用 Bash for Windows(例如 Git Bash

$ source .venv/Scripts/activate

该命令将创建或修改一些将可用于下一个命令的 环境变量

其中一个变量是PATH变量。

提示

您可以在 环境变量 部分中详细了解PATH环境变量。

激活虚拟环境会将它的路径.venv/bin(在 Linux 和 macOS 上)或.venv\Scripts(在 Windows 上)添加到PATH环境变量中。

假设在激活环境之前,PATH变量看起来像这样

/usr/bin:/bin:/usr/sbin:/sbin

这意味着系统将在以下位置查找程序:

  • /usr/bin
  • /bin
  • /usr/sbin
  • /sbin
C:\Windows\System32

这意味着系统将在以下位置查找程序:

  • C:\Windows\System32

激活虚拟环境后,PATH变量将看起来像这样

/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin

这意味着系统现在将首先在以下位置查找程序:

/home/user/code/awesome-project/.venv/bin

然后再在其他目录中查找。

因此,当您在终端中键入python时,系统将在以下位置找到 Python 程序:

/home/user/code/awesome-project/.venv/bin/python

并使用该程序。

C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32

这意味着系统现在将首先在以下位置查找程序:

C:\Users\user\code\awesome-project\.venv\Scripts

然后再在其他目录中查找。

因此,当您在终端中键入python时,系统将在以下位置找到 Python 程序:

C:\Users\user\code\awesome-project\.venv\Scripts\python

并使用该程序。

一个重要的细节是,它会将虚拟环境路径放在PATH变量的开头。系统会在找到任何其他可用的 Python 之前找到它。这样,当你运行python时,它将使用虚拟环境中的 Python,而不是任何其他python(例如,全局环境中的python)。

激活虚拟环境还会改变其他一些东西,但这只是它最重要的功能之一。

检查虚拟环境

当你检查虚拟环境是否处于活动状态时,例如使用

$ which python

/home/user/code/awesome-project/.venv/bin/python
$ Get-Command python

C:\Users\user\code\awesome-project\.venv\Scripts\python

这意味着将使用的python程序是虚拟环境中的程序。

在 Linux 和 macOS 中使用which,在 Windows PowerShell 中使用Get-Command

该命令的工作原理是,它将在PATH环境变量中查找,按顺序遍历每个路径,查找名为python的程序。一旦找到它,它将向你显示该程序的路径

最重要的是,当你调用python时,这正是将被执行的 "python"。

因此,你可以确认你是否在正确的虚拟环境中。

提示

很容易激活一个虚拟环境,获取一个 Python,然后转到另一个项目

而第二个项目将无法运行,因为你使用了错误的 Python,它来自另一个项目的虚拟环境。

能够检查正在使用的python非常有用。🤓

为什么要停用虚拟环境

例如,你可能正在处理一个名为philosophers-stone的项目,激活该虚拟环境,安装包并使用该环境。

然后你想处理另一个项目prisoner-of-azkaban

你转到该项目

$ cd ~/code/prisoner-of-azkaban

如果你没有停用philosophers-stone的虚拟环境,当你运行终端中的python时,它将尝试使用来自philosophers-stone的 Python。

$ cd ~/code/prisoner-of-azkaban

$ python main.py

// Error importing sirius, it's not installed 😱
Traceback (most recent call last):
    File "main.py", line 1, in <module>
        import sirius

但是,如果你停用虚拟环境并激活prisoner-of-askaban的新虚拟环境,那么当你运行python时,它将使用prisoner-of-azkaban的虚拟环境中的 Python。

$ cd ~/code/prisoner-of-azkaban

// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎
$ deactivate

// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀
$ source .venv/bin/activate

// Now when you run python, it will find the package sirius installed in this virtual environment ✨
$ python main.py

I solemnly swear 🐺

备选方案

这是一份简单的入门指南,它将教你如何了解底层的工作原理。

有许多备选方案可以用来管理虚拟环境、包依赖关系(需求)和项目。

一旦你准备好了,想使用一个工具来管理整个项目,包括包依赖关系、虚拟环境等等,我建议你尝试使用 uv

uv 可以做很多事情,它可以

  • 为你安装 Python,包括不同的版本
  • 管理你项目的虚拟环境
  • 安装
  • 管理你项目的包依赖关系和版本
  • 确保你有一个精确的包和版本集要安装,包括它们的依赖关系,这样你就可以确保你的项目在生产环境中的运行方式与你在开发过程中使用的计算机上完全相同,这被称为锁定
  • 以及其他许多功能

总结

如果你阅读并理解了所有这些内容,那么你现在比很多开发人员更了解虚拟环境。🤓

了解这些细节很有可能在将来调试看似复杂的问题时有所帮助,但你会知道它的底层工作原理。😎