首页 > 解决方案 > 系统上的软件包更新会影响虚拟环境?

问题描述

我在虚拟环境中。我在我的活动终端中验证了这一点,which python并且可以确认我实际上是在虚拟环境中。打印pip list,根据官方文档,应该列出这个虚拟环境中的包。这是一个输出:

Package                            Version            
---------------------------------- -------------------
alabaster                          0.7.10             
anaconda-client                    1.6.5         
... (truncated)
pip                                10.0.1             

You are using pip version 10.0.1, however version 18.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

当我启动另一个终端时,这次确保我不在那个虚拟环境中并继续升级pip

pip install --upgrade pip

这样做后,我验证了我pip系统上的包已更新到版本 18.0。这是令人困惑的部分:我切换回虚拟环境并使用,我的虚拟环境pip list中的 pip 版本现在是 pip 18.0。

为什么在该环境之外升级 pip 版本随后从 10.0.1 更新我的虚拟环境中的 pip?我是否误解了虚拟环境的工作原理?我对python并不陌生,但没有使用过虚拟环境,所以如果它是非常基础的东西,请原谅我。据我了解,使用虚拟环境的主要价值是我可以升级我的系统范围的包(例如 pip、flask 等),而不会影响我的虚拟环境中的任何更改。虚拟环境应该是孤立的环境吗?

如果重要的话,我使用的是默认venv而不是virtualenvwrapper任何其他包装工具。

标签: pythoncondavirtual-environment

解决方案


问题

tl; dr:问题出在 conda 上。我使用 conda,显然这会导致在通过创建的虚拟环境中管理和安装软件包时出现一些问题,venv因为本地实例pip不存在。

解决方案 A:conda install -n myenv pip其中myenv指的是您的虚拟环境的名称

解决方案 B:使用conda list,conda create以与 conda 100% 兼容的方式处理环境

/结束 tl;博士

这是问题的细分。当我使用 anaconda 的 python 版本时,我决定查看我环境中的软件包列表;假设我打电话给pip freezeor pip list,我是否在虚拟环境中都没有关系。site-packages它从 conda 的相应文件夹返回完全相同的包列表。

当我在虚拟环境中时, runningwhich python似乎确实指向 python 实例的隔离版本(acco是该实例的名称):

(acco) Samuels-MacBook-Pro:Accomplish Samuel$ which python
/Users/Samuel/Dropbox/Projects/Python/Acco/acco/bin/python 

然而,在这个虚拟环境中,运行pip list还是pip list --local会引用同一组包——那是因为它仍然指向 conda 版本的包目录(是的,即使在虚拟环境中也是如此)。

具体来说,无论有无,在虚拟环境内部或外部,pip list指向安装在/anaconda3/lib/../site-packages目录中的包:

import sys
sys.prefix
'/Users/Samuel/anaconda3'    

import site
site.getsitepackages()
['/Users/Samuel/anaconda3/lib/python3.6/site-packages']

真正有问题的部分是,在虚拟环境中,您基本上没有安装任何库。如果您尝试安装的任何软件包已经存在于 conda 的目录中,则从requirements.txt' usingpip install -r requirements.txt or just installing packages at all using plain oldpip install 安装将不起作用。相反,您会收到一条看起来不像错误的消息,并且它就停在那里。您尝试安装的软件包未安装到本地目录中。

# same as pip install Flask==0.12.2
pip install -r requirements.txt 
Requirement already satisfied: Flask==0.12.2 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (0.12.2)
Requirement already satisfied: Werkzeug>=0.7 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from Flask==0.12.2->-r requirements.txt (line 1)) (0.12.2)
Requirement already satisfied: Jinja2>=2.4 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from Flask==0.12.2->-r requirements.txt (line 1)) (2.9.6)
Requirement already satisfied: itsdangerous>=0.21 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from Flask==0.12.2->-r requirements.txt (line 1)) (0.24)
Requirement already satisfied: click>=2.0 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from Flask==0.12.2->-r requirements.txt (line 1)) (6.7)
Requirement already satisfied: MarkupSafe>=0.23 in /Users/Samuel/anaconda3/lib/python3.6/site-packages (from Jinja2>=2.4->Flask==0.12.2->-r requirements.txt (line 1)) (1.0)

提醒一下,我们仍然在我们的虚拟环境 ( ../Dropbox/Projects/Python/Acco/acco/bin/python) 中使用 python 执行您的 python 命令,而不是 conda 发行版。此虚拟环境在其隔离文件夹中没有包lib,并且您无法将任何库安装到其中,因为pip“要求已满足”消息将停止并退出(或终止其尝试)。

这意味着在该虚拟环境中,尝试运行具有依赖项的 python 脚本或应用程序肯定会失败。从上面的示例构建,您的 Flask 应用程序app.py将无法运行,因为它找不到flask. 不用说,因为你的虚拟环境没有包,它不会让你安装任何包。


解决方案

解决方案是,如果您使用的是 python 的 conda 发行版,请检查您已安装在系统上的软件包,conda list而不是pip list最大程度地保持一致性。

(acco) Samuels-MacBook-Pro:Acco Samuel$ conda list
# packages in environment at /Users/Samuel/anaconda3:
#
# Name                    Version                   Build  Channel
_ipyw_jlab_nb_ext_conf    0.1.0            py36h2fc01ae_0
_r-mutex                  1.0.0                     mro_2
alabaster                 0.7.10           py36h174008c_0
anaconda                  custom           py36ha4fed55_0

请注意,它conda告诉您列出库的环境。在这个阶段:

  1. 使用停用环境deactive
  2. 使用 制作虚拟环境conda create --name acco python=3.6.3 flask sqlite,这里我们使用acco虚拟环境的名称、特定版本的 python 以及可选的其他一些依赖项
  3. 使用激活环境source activate acco

现在,当你conda list再次这样做时,在你的虚拟环境中:

# packages in environment at /Users/Samuel/anaconda3/envs/acco:
#
# Name                    Version                   Build  Channel
ca-certificates           2018.03.07                    0
certifi                   2018.8.13                py36_0
click                     6.7              py36hec950be_0
flask                     1.0.2                    py36_1

如果您想使用老式requirement.txt文件管理应用程序的依赖项,那么最简单的方法是conda list --export > requirements.txt. 从这一点开始,使用conda list代替pip list和使用conda create以及source activate代替其venv对应物。

anaconda 的主要文档建议:

要在您的环境中使用 pip,请在终端窗口或 Anaconda 提示符中运行:

conda install -n acco pip 
source activate acco 
pip <pip_subcommand>

该解决方案也有效。按照上面的步骤,我最终得到:

(acco) Samuels-MacBook-Pro:Accomplish Samuel$ pip list
Package      Version
------------ ---------
certifi      2018.8.13
click        6.7
Flask        1.0.2
itsdangerous 0.24
Jinja2       2.10
MarkupSafe   1.0
pip          10.0.1
setuptools   40.0.0
Werkzeug     0.14.1
wheel        0.31.1

作为奖励,我仔细检查了以这种方式创建的 conda 环境是否能够处理pip listor pip install: 相同的错误。但是,当使用conda update(例如conda update sqlite:)conda install或任何 conda-counterpart 代码时,它们都按预期工作。在您的本地环境中更新sqlite完全更新该副本,sqlite而不是您的 anaconda 系统中的副本。哇!


推荐阅读