跳到内容

虚拟环境

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

信息

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

提示

虚拟环境环境变量不同。

环境变量是系统中可以被程序使用的变量。

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

信息

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

如果您准备好采用一个可以为您管理一切工具(包括安装 Python),请尝试 uv

创建项目

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

我通常的做法是在我的 home/用户目录下创建一个名为 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

或者如果您使用 Windows 的 Bash (例如 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 sqlmodel

---> 100%

如果你有 uv

$ uv pip install sqlmodel
---> 100%

requirements.txt 安装

如果你有一个 requirements.txt 文件,现在可以使用它来安装其中的包。

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

如果你有 uv

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

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

sqlmodel==0.13.0
rich==13.7.1

运行你的程序

激活虚拟环境后,你可以运行你的程序,它将使用你虚拟环境中的 Python 以及你在其中安装的包。

$ python main.py

Hello World

配置你的编辑器

你可能会使用编辑器,请确保将其配置为使用你创建的同一个虚拟环境(它可能会自动检测到),这样你就可以获得自动补全和内联错误提示。

例如

提示

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

停用虚拟环境

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

$ deactivate

这样,当你运行 python 时,它将不会尝试从该虚拟环境及其安装的包中运行。

准备工作

现在你已经准备好开始你的项目了。

提示

你想了解以上所有内容吗?

继续阅读。👇🤓

为什么使用虚拟环境

要使用 SQLModel,你需要安装 Python

之后,你需要安装 SQLModel 和任何其他你想使用的

要安装包,你通常会使用 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 sqlmodel
---> 100%

这将下载一个包含 SQLModel 代码的压缩文件,通常来自 PyPI

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

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

默认情况下,它会将下载和提取的文件放在你的 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

或者如果您使用 Windows 的 Bash (例如 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,包括不同的版本
  • 管理你的项目的虚拟环境
  • 安装
  • 管理你的项目的包依赖项和版本
  • 确保你有一组确切的包和版本要安装,包括它们的依赖项,这样你就可以确保你可以在生产环境中运行你的项目,就像在开发时在你的计算机上一样,这称为锁定
  • 以及其他很多事情

结论

如果你阅读并理解了所有这些,现在你对虚拟环境的了解比许多开发人员都多。🤓

了解这些细节很可能在将来调试看起来很复杂的东西时很有用,但你将了解它的底层工作原理。😎