虚拟环境¶
当您在 Python 项目中工作时,您可能应该使用虚拟环境(或类似的机制)来隔离您为每个项目安装的包。
信息
如果您已经了解虚拟环境、如何创建和使用它们,您可能想跳过本节。 🤓
提示
虚拟环境与环境变量不同。
环境变量是系统中可以被程序使用的变量。
虚拟环境是一个包含一些文件的目录。
创建项目¶
首先,为您的项目创建一个目录。
我通常的做法是在我的 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
中创建虚拟环境
该命令在名为 .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.txt
或 pyproject.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,包括不同的版本
- 管理你的项目的虚拟环境
- 安装包
- 管理你的项目的包依赖项和版本
- 确保你有一组确切的包和版本要安装,包括它们的依赖项,这样你就可以确保你可以在生产环境中运行你的项目,就像在开发时在你的计算机上一样,这称为锁定
- 以及其他很多事情
结论¶
如果你阅读并理解了所有这些,现在你对虚拟环境的了解比许多开发人员都多。🤓
了解这些细节很可能在将来调试看起来很复杂的东西时很有用,但你将了解它的底层工作原理。😎