影响虚拟环境的系统包更新?

Package updates on the system affecting virtual environment?

我在虚拟环境中。我在我的活动终端中使用 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 或任何其他包装工具。

问题

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

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

解决方案 B:使用 conda listconda create 以与 conda

100% 兼容的方式处理环境

/结束 tl;dr

这是问题的细分。当我使用 anaconda 的 python 版本时,我决定查看我环境中的软件包列表;假设我要调用 pip freezepip list,无论我是否在虚拟环境中都无关紧要。它 returns 与 conda 对应的 site-packages 文件夹中的包列表完全相同。

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

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

然而,在这个虚拟环境中,运行ning pip listpip list --local 仍会引用同一组包 - 这是因为它仍然指向conda 版本的包目录(是的,even 在虚拟环境中)。

具体来说,有或没有,在虚拟环境之内或之外,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.txtor 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 而不是 conda 分发版来执行您的 python 命令。此虚拟环境在其隔离的 lib 文件夹中没有包,并且您无法在其中安装任何库,因为 pip 将因 "requirement already satisfied" 消息而停止并退出(或终止其尝试).

这意味着在该虚拟环境中,尝试 运行 具有依赖项的 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. 停用环境
  3. 使用 conda create --name acco python=3.6.3 flask sqlite 创建虚拟环境,这里我们使用 acco 作为虚拟环境的名称,特定版本的 python,以及可选的一些其他依赖项
  4. 激活环境使用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 createsource activate 代替 venv

anaconda's main documentation建议:

To use pip in your environment, in your Terminal window or an Anaconda Prompt, run:

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 listpip install:相同的错误。但是,当使用 conda update(例如:conda update sqlite)、conda install 或任何 conda-counterpart 代码时,它们都可以正常工作。在本地环境中更新 sqlite 会准确更新 sqlite 的副本,而不是 anaconda 系统中的副本。哇!