LastEditTime : 2023-12-15 21:42:49
0x00 前言
随着Python项目越来越多,很容易出现Python版本或者包的混乱、污染,导致原本已完成的项目出错,致使开发效率大大降低。
比如早期项目A开发完成后,因为新项目B中的Python版本或者包的更新,导致项目A的运行出错等一系列不兼容问题,那么一个隔离的虚拟环境(虚拟环境中包含了Python解释器的一个副本,并且在该虚拟环境中安装与卸载的包都只会影响到使用该虚拟环境的项目。)将使不同的项目之间互不干扰,并且提高了开发效率。
在VSCode中可以配置多个虚拟环境来适配不同的项目需求。
谨以此文作为个人学习笔记方便以后查阅。
-
本文所使用的环境:
- Os: Windows_NT x64 10.0.19045
- Python: Python3.8.2 & Python3.12.1
- Editor: VSCode Version: 1.85.0 (user setup)
- Terminal: PowerShell
0x01 多版本Python之"py"与"python"的区别以及pip的日常使用
1. pip
pip
是Python包的管理工具。提供了对Python包的安装、查看、升级、卸载等功能。
a. 更新pip
python -m pip install --upgrade pip
注意:
python
命令介绍请看下文。
b. 重装pip
Python附带了一个ensurepip
模块,它可以在当前Python环境中安装pip
。如果pip
因为一些意外情况导致出现无法运行的错误,可以直接执行以下命令重装它:
python -m ensurepip --upgrade
c. pip命令代码补全
pip
除了支持 bash、zsh 和 Fish 中的命令行补全之外,还支持PowerShell,需要在PowerShell配置文件$PROFILE
中添加补全代码即可:
python -m pip completion --powershell | Out-File -Encoding default -Append $PROFILE
重启PowerShell
或者执行命令.$PROFILE
即可生效。
但是经过测试,发现补全效果不是很好,只有默认pip
可以识别补全,"python -m pip"
、"py -m pip"
这两种都无法识别 ,我们可以稍微修改一下代码,在PowerShell
中输入:
notepad $PROFILE
在弹出的文本编辑窗口中按以下代码修改一下之前添加的补全代码即可:
# pip powershell completion start
if ((Test-Path Function:\TabExpansion) -and -not `
(Test-Path Function:\_pip_completeBackup)) {
Rename-Item Function:\TabExpansion _pip_completeBackup
}
function TabExpansion($line, $lastWord) {
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
if ($lastBlock.StartsWith("pip ")) {
$Env:COMP_WORDS=$lastBlock
$Env:COMP_CWORD=$lastBlock.Split().Length - 1
$Env:PIP_AUTO_COMPLETE=1
(& pip).Split()
Remove-Item Env:COMP_WORDS
Remove-Item Env:COMP_CWORD
Remove-Item Env:PIP_AUTO_COMPLETE
}
elseif ($lastBlock.StartsWith("py -m pip ")) {
$Env:COMP_WORDS=$lastBlock
$Env:COMP_CWORD=$lastBlock.Split().Length - 1
$Env:PIP_AUTO_COMPLETE=1
(& py -m pip).Split()
Remove-Item Env:COMP_WORDS
Remove-Item Env:COMP_CWORD
Remove-Item Env:PIP_AUTO_COMPLETE
}
elseif ($lastBlock.StartsWith("python -m pip ")) {
$Env:COMP_WORDS=$lastBlock
$Env:COMP_CWORD=$lastBlock.Split().Length - 1
$Env:PIP_AUTO_COMPLETE=1
(& python -m pip).Split()
Remove-Item Env:COMP_WORDS
Remove-Item Env:COMP_CWORD
Remove-Item Env:PIP_AUTO_COMPLETE
}
elseif (Test-Path Function:\_pip_completeBackup) {
# Fall back on existing tab expansion
_pip_completeBackup $line $lastWord
}
}
# pip powershell completion end
以上代码保存之后,重启PowerShell
或者执行命令.$PROFILE
即可生效。再次测试除了补全速度稍微慢一点之外,完美的识别了三种pip
命令的代码补全。
d. 安装软件包
以常用的requests
包为例:
# 从官方镜像源中安装requests最新版本包
pip install requests
install
命令默认安装最新版本的包,如果项目有版本要求,那么应该注意安装的版本,可以使用<package name>==<version>
来指定单独安装的包版本:
# 从官方镜像源中安装requests2.18.1版本包
pip install requests==2.18.1
用以上方法安装指定版本的包时,如果本身已安装过了,那么此时会覆盖原先已安装的版本。
对于版本号管理有以下几种格式:
- == 指定版本号
- => 高于此版本号
- <= 小于此版本号
- < 小于此版本号
- > 大于此版本号
还可以使用requirements.txt
文件来批量安装软件包,requirements文件内容一般包含了软件包名称与软件包的版本号,它可以是自己手动写入修改,也可以是从已安装的包环境中导出的(下文有介绍):
# 根据requirements.txt文件批量安装软件包
pip install -r requirements.txt
e. 设置软件包的镜像源
install
命令可以带一个-i <url>
选项,此选项是包索引选项,-i
选项后面可附带包所在的镜像源网址<url>
;如果install
命令不带-i
选项,那么默认会从官方镜像源安装包,此时很有可能网速会受限下载很慢,那么-i
选项就很有必要了,它可以更改指定成国内访问速度比较快的镜像源网址<url>
:
# 从指定镜像源网址中安装requests包
pip install -i https://pypi.mirrors.ustc.edu.cn/simple/ requests
# 从指定镜像源网址中批量安装requirements.txt中的包
pip install -i https://pypi.mirrors.ustc.edu.cn/simple/ -r requirements.txt
国内访问速度比较快的镜像源网址有:
# 阿里云
https://mirrors.aliyun.com/pypi/simple/
# 百度云
https://mirror.baidu.com/pypi/simple/
# 腾讯云
https://mirrors.cloud.tencent.com/pypi/simple/
# 华为云
https://mirrors.huaweicloud.com/repository/pypi/simple/
# 网易
https://mirrors.163.com/pypi/simple/
# 豆瓣
https://pypi.doubanio.com/simple/
# 中科大
https://pypi.mirrors.ustc.edu.cn/simple/
# 清华大学
https://pypi.tuna.tsinghua.edu.cn/simple/
f. pip配置文件
除了可以在命令行设置软件包的镜像源之外,pip
还支持配置文件pin.ini
,配置文件可以更改命令行选项的默认值。它们是使用标准INI样式的配置文件编写的。这样每次执行命令时都会有配置文件进行约束,大大减少了不必要的麻烦。
查找pip.ini
配置文件所在位置的命令:
pip config list -v
# 多版本Python可以用py命令执行对应版本的pip
py -3.8 -m pip config list -v #python3.8版本
py -3.12 -m pip config list -v #python3.12版本
关于py
命令的介绍,后文会有讲解,这里先略过,命令执行结果如下:
上面列出的是pip
试图加载配置文件的顺序,至于variant
后面表示的含义,pip官网有详细的介绍:
pip has 3 “levels” of configuration files:
- global: system-wide configuration file, shared across users.
- user: per-user configuration file.
- site: per-environment configuration file; i.e. per-virtualenv.
从中可以看出pip
的配置文件位置有三种:系统级配置文件、用户配置文件和当前环境配置文件;另外,前面的global
、user
这两类的配置文件对于多版本Python来说是可以通用的,而唯一有区别的是site
级的配置文件,它位于当前版本下的安装目录中。
所以对于怎么来设置pip
的配置文件pip.ini
,就看个人喜好了,想一次配置多版本通用,那么设置global
、user
;想在每个版本都给它设置一个,那么可以设置site
。
注意:上述
pip config list -v
命令列出的 4 个配置文件,是按由上至下的顺序逐级加载,如果有相同的参数名称, 后面加载的会覆盖前面的。
接下来是配置pip.ini
,这里选用户级的配置文件:user
(使用对应的选项--user
)。如果不清楚文件是否存在,那么可以使用以下命令:
pip config --user set global.index-url https://mirrors.aliyun.com/pypi/simple/
pip config --user set install.trusted-host mirrors.aliyun.com
该命令会在pip.ini
文件不存在时,在文件夹:%APPDATA%\pip
(在文件资源管理器的地址栏中输入回车即可跳转到该目录)下自动新建一个pip.ini
文件,如果文件存在,那么会覆盖掉对应变量的值。
执行完上述命令后,想要修改的话,可以在PowerShell
中输入以下命令并回车:
pip config edit --editor notepad
此时会使用记事本来打开pip.ini
文件,参考以下内容修改保存即可:
[global]
# 设置默认的软件包安装源为PyPI(Python软件包索引)
index-url = https://mirrors.aliyun.com/pypi/simple/
# 额外的软件包安装源
extra-index-url = https://mirror.baidu.com/pypi/simple/
https://mirrors.cloud.tencent.com/pypi/simple/
https://mirrors.huaweicloud.com/repository/pypi/simple/
https://mirrors.163.com/pypi/simple/
https://pypi.doubanio.com/simple/
https://pypi.mirrors.ustc.edu.cn/simple/
https://pypi.tuna.tsinghua.edu.cn/simple/
# 设置socket超时时间100s(默认为15s)。
timeout = 100
# 关闭pip版本检查
disable-pip-version-check = true
[install]
# 用于指定可信任的主机,以解决一些安全警告。
trusted-host = mirrors.aliyun.com
mirror.baidu.com
mirrors.cloud.tencent.com
mirrors.huaweicloud.com
mirrors.163.com
pypi.doubanio.com
pypi.mirrors.ustc.edu.cn
pypi.tuna.tsinghua.edu.cn
注意:保存
pip.ini
文件时,需要选择编码格式为:ANSI,否则会报错:Configuration file contains invalid cp936 characters
g. 查看已安装的软件包
上面说到requirements.txt
文件,该文件内容一般包含了软件包名称与软件包的版本号,它可以是自己手动写入修改,也可以是从已安装的软件包环境中导出的,所以pip
支持已安装软件包查看及相关信息导出:
# 列出已安装的软件包
pip list
# 以requirements格式输出已安装包的列表
pip freeze
# 将以requirements格式输出已安装包的列表内容保存到requirements.txt文件中
pip freeze > requirements.txt
导出的requirements.txt
文件具体内容以个人已安装的包为准,一般是包名称==版本号
:
h. 升级已安装的软件包
以常用的requests
包为例:
# 将`requests`包升级到最新版本
pip install -U requests
i. 卸载已安装的软件包
以常用的requests
包为例:
pip uninstall requests
2. py
py
是python3.3版本以后才引入的适用于 Windows 的 Python 启动器
,是一个位于C:\Windows\py.exe
的程序,可帮助定位和执行不同的 Python 版本。
关于它的具体使用方法,可以在命令行中执行py -h
查看。比较常用的命令有:
a. 列出(定位)当前系统下所有已安装的Python版本以及安装目录
# py -0 不带目录
py -0p
b. 启动不同版本的python.exe
,可以使用py -x.y
# 启动已安装的python2.X版本
py -2
# 启动已安装的python3.8版本
py -3.8
# 启动已安装的python3.12版本
py -3.12
如果直接使用py
命令,那么它将默认启动最新安装的python版本,如果想临时更改(重启PowerShell
后无效)启动的Python版本,可以在PowerShell
中设置PYTHON环境变量:$Env:PY_PYTHON
比如在PowerShell
中输入:
$Env:PY_PYTHON = 3.8
# 此时py启动的是Python3.8版本
py
$Env:PY_PYTHON = 3.12
# 此时py启动的是Python3.12版本
py
c. 启动不同版本的pip
默认情况下使用pip
命令,启动的是最新安装的Python版本下的pip
,如果想操作不同版本的pip
时,那么只需要在pip
前面加上py -x.y -m
即可,其它参数与默认情况下使用pip
命令时一致,简单举几个例子:
# 列出python3.12下已安装的包
py -3.12 -m pip list
# 以requirements格式输出python3.8下的安装包列表
py -3.8 -m pip freeze
# 将以requirements格式输出python3.8下已安装包的列表内容保存到requirements.txt文件中
py -3.8 -m pip freeze > requirements.txt
# 将以requirements格式输出python3.12下已安装包的列表内容保存到requirements.txt文件中
py -3.12 -m pip freeze > requirements.txt
当然还可以先设置$Env:PY_PYTHON
变量值后,直接使用py -m
,具体使用哪种方法看个人喜好。
$Env:PY_PYTHON = 3.8
# 以requirements格式输出python3.8下的安装包列表
py -m pip freeze
更多使用方法请查看:pip -h
3. python
python
命令不能像py
命令一样直接指定启动的Python版本,因为它本身执行的其实就是Python安装目录下的python.exe
文件(比如:C:\Programs\Python\Python38\python.exe
),且它执行的Python版本还会受系统的环境变量Path
所影响,优先执行环境变量Path
的值最上面(前面)的一个版本。
从上文对py
的介绍中大致可以看出,py
比python
功能更强大,不仅可以启动任意安装的Python版本,而且对pip
命令也可以指定版本来启动,所以日常使用中更推荐使用py
。
0x02 在VSCode中切换Python解释器版本
本文使用的VSCode版本是V1.85.0 (user setup)
a. 当编辑.py文件
时,在底部命令栏的右下角可以直接点击切换当前Python文件使用的解释器版本
b. 也可以使用快捷键Ctrl+Shift+p
调出命令面板,面板中输入Python:Select Interpreter
按回车。
以上两个方法均可调出一个Python解释器选项:
点击想要的Python解释器版本即可。选完之后,右下角会显示当前生效的Python解释器版本。
此时快捷键F5
运行的即为当前选择的Python解释器版本。
0x03 在VSCode中配置Python虚拟环境
1. 使用PowerShell手动创建Python虚拟环境
Python虚拟环境的创建有四种方式,分别是:pipenv、venv、cirtualenv、conda
个人比较习惯使用venv
来创建虚拟环境,其它的有兴趣可以自行查找资料。
venv
模块支持创建轻量的“虚拟环境”,每个虚拟环境将拥有它们自己独立的安装在其 site-packages
目录中的 Python 软件包集合。
以下命令行的操作均在PowerShell
中进行。
a. 创建虚拟环境
创建虚拟环境前需要考虑虚拟环境存放位置,一般新建一个文件夹即可(当然不新建也可以,因为创建虚拟环境时,同时也会生成一个以虚拟环境名称命名的文件夹,具体操作看个人喜好。),例如:D:\PythonVenv
,然后进入该文件夹进行虚拟环境的创建:
# 进入PythonVenv文件夹中
cd D:\PythonVenv
# 创建python3.8版本的虚拟环境py38
py -3.8 -m venv py38
这里py38
是虚拟环境的名称,可以自己任意命名,另外创建完成后会生成一个py38
文件夹,里面包含了python3.8版本的解释器“副本”,并把python3.8版本的标准包复制了一份。
注意:这里使用了
py
命令指定Python版本来创建虚拟环境,如果用python
命令(即python -m venv py38
)则需要注意当前Python的版本,所以一般能用py
还是尽量用py
,这样在多版本Python下创建虚拟环境更清晰明了。
b. 激活虚拟环境
使用venv
创建完虚拟环境py38
之后,虚拟环境必须激活才能使用,激活方式是在py38\Scripts
文件夹下,运行.\activate
或者.\Activate.ps1
命令即可,退出时则使用deactivate
命令,注意这里deactivate
跟.\activate
不同,不能加文件路径.\
:
# 进入Scripts文件夹
cd .\py38\Scripts
# 激活虚拟环境
# 也可用 .\Activate.ps1
.\activate
# 退出虚拟环境
deactivate
虚拟环境激活后,在命令提示符前会(py38)
表示当前进入虚拟环境中,此时不管是py
还是python
默认使用的都是Python3.8版本(因为创建时已指定py -3.8
)。
c. 激活出错
如果激活时出现错误,那么应该就是当前PowerShell
的执行策略不允许执行激活脚本:
首先查看影响当前会话的所有执行策略,并按优先级顺序
显示它们,可以执行命令:
Get-ExecutionPolicy -List
这里主要关心 CurrentUser
,因为当前用户的执行策略优先于本地计算机设置的执行策略。可以看到它是Restricted
Restricted
- Windows 客户端计算机的默认执行策略。
- 允许单个命令,但不允许脚本。
- 阻止运行所有脚本文件,包括格式和配置文件 (.ps1xml)、模块脚本文件 (.psm1) 和 PowerShell 配置文件 (.ps1)。
此时如果想更改此执行策略,则可用以下命令来更改执行策略:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
执行命令后,按提示输入y
,回车即可。运行效果如下图所示:
可以看到当前执行策略已被更改成:RemoteSigned
RemoteSigned
- Windows 服务器计算机的默认执行策略。
- 脚本可以运行。
- 需要受信任的发布者对从 Internet 下载的脚本和配置文件(包括电子邮件和即时消息程序)的数字签名。
- 在本地计算机上编写且不是从 Internet 下载的脚本不需要数字签名。
- 如果脚本已解除阻止(例如通过使用 Unblock-File cmdlet),则运行从 Internet 下载且未签名的脚本。
- 存在运行来自 Internet 以外来源的未签名脚本以及可能存在恶意的签名脚本的风险。
此时重新执行激活脚本即可。
注意:
Set-ExecutionPolicy
命令更改执行策略立即生效。 无需重启 PowerShell。如果为 LocalMachine(需要“以管理员身份运行”选项启动 PowerShell) 或 CurrentUser 作用域设置执行策略,则更改将保存在注册表中并保持有效,直到再次更改为止。
d. 在虚拟环境中安装软件包
激活虚拟环境后,安装软件包的操作跟真实环境一样,且这时在虚拟环境中已经不需要在考虑版本问题,直接使用python
、pip
命令操作即可,例如:
# 列出已安装软件包
pip freeze
# 安装requests包
pip install requests
# 列出已安装软件包
pip freeze
执行效果如下:
requests包
被安装在py38\Lib\site-packages
文件夹中。另外可以看出虚拟环境非常干净,与真实的Python3.8版本完全隔开,另外,WARNING
提示当前可以更新pip
的版本,执行以下命令更新pip
:
# 更新pip版本
python -m pip install --upgrade pip
注意:如果pip命令不存在,则可以使用命令:
python -m pip install --upgrade pip
,重新安装 pip。
e. 虚拟环境中设置配置文件
前文已经介绍了pip
有3个级别的配置文件,在虚拟环境中也是适用的:
pip config list -v
可以看出虚拟环境中的pip
依然可以加载真实环境中global
和user
这两个级别的配置文件,如果想要彻底隔离开配置文件,那么可以参考前文的设置步骤,设置一个site
级别的配置文件即可。
2. 使用VSCode创建Python虚拟环境
首先安装完Python之后,还需要在VSCode中安装Python的插件
准备工作做完之后选择一个存放Python虚拟环境的文件夹,这里需要注意:如果是在项目文件夹下打开VSCode,那么用它创建的虚拟环境会保存在当前项目文件夹中。所以虚拟环境的存放位置需要自己考虑清楚。
这里依然拿D:\PythonVenv
举例,直接鼠标右键它并选择 通过 Code 打开
。
这里显示的py38
是之前手动创建的虚拟环境,不用管它。按快捷键Ctrl+Shift+p
打开命令面板,输入Python:Create Environment
回车
选择Venv
选择一个Python解释器版本,例如:Python 3.8.2 64-bit
等待创建完成即可:
创建完成后,左边多了一个.venv
文件夹,同时也是虚拟环境的名称,文件夹里面的文件和手动创建的虚拟环境py38
是一样的,只是虚拟环境名称不一样。
3. 在VSCode中切换Python虚拟环境
切换之前需要做一些配置,这样打开项目的时候才可以自动识别所有虚拟环境。
在VSCode的settings.json
文件中,添加以下设置:
// 进入PowerShell时自动激活虚拟环境
"python.terminal.activateEnvironment": true,
// 虚拟环境存放路径
"python.venvPath": "D:\\PythonVenv",
重启VSCode之后,随便打开一个.py
文件,在编辑器底部命令栏的右下角直接点击切换即可
可以看到,两个虚拟环境都正确识别了
点击选择py38
虚拟环境后,右下角会显示当前生效的虚拟环境,然后按快捷键 " Ctrl+Shift+` " 打开终端,我这里设置成PowerShell了
打开终端后稍微等待一会儿,右下角会自动弹窗提示虚拟环境激活成功,这时在终端中可以随意使用虚拟环境了。
4. 总结
手动创建虽然比VSCode创建麻烦一些,但是相比来说更自由,名字、存放路径可以自由选择,VSCode创建的虚拟环境只能默认命名:.venv
,且如果在同一目录下,只能创建一个.venv
虚拟环境
当然如果是一个项目中创建一个虚拟环境这样问题到不大,如果想像手动创建那样,都存放在一个目录下,那样就得在新建一层目录,比如:D:\PythonVenv\dir1\.venv
、D:\PythonVenv\dir2\.venv
、D:\PythonVenv\dir3\.venv
... 这样会有一个问题,VSCode的"python.venvPath": "D:\\PythonVenv"
设置说明:
Virtual environments located in the folder identified by the
python.venvPath
setting (see General Python settings), which can contain multiple virtual environments. The extension looks for virtual environments in the first-level subfolders ofvenvPath
.
所以当它还有一层dir1
、dir2
、dir3
... 文件夹时无法自动识别到虚拟环境,并且它只能配置一个文件夹,类似"python.venvPath": "D:\\PythonVenv, D:\\PythonVenv\dir1"
这样设置多文件夹是无法使用的。这么一来想使用其它虚拟环境,那就只能手动选择该环境的目录了:
因此,我个人更喜欢手动创建虚拟环境,这样存放路径统一,使用更方便,也更好管理。
【参考资料】