pip在哪里安装带有虚拟环境的包?
Where does pip install packages with a virtual environment?
情况: 我已经创建了一个虚拟环境并使用显式路径 运行 pip
(没有采购 activate
)。它是在全局 dist-packages
中安装软件包还是在虚拟环境的 site-packages
中安装它们。
详情:
正如 所解释的那样,当与虚拟环境一起使用时,pip 会在 <virtualenv_name>/lib/<python_ver>/site-packages
中安装软件包。根据我的经验,当我激活 virtualenv 时,情况确实如此。我有一个现有的 bash 脚本,它直接指向 pip
可执行文件而无需激活 virtualenv。这仍然会在 virtualenv 的站点包中安装包吗?还是将它们安装在 /local/lib/<python-version>/dist-packages
?
注意:我在 Ubuntu 16.04
这在很大程度上取决于 哪个 版本(不是语义版本意义上的,而是在创建 venv 时安装的 pip 的 having-multiple-"versions" ) 您的脚本正在使用的 pip 及其配置(可能包括您的环境)。
假设您的脚本有这样一行
/some/path/to/pip install <some package>
假设pip至少安装了一个包,你可以使用
/some/path/to/pip show <that package>
它会给你如下的输出:
$ pip show numpy
Name: numpy
Version: 1.14.5
Summary: NumPy: array processing for numbers, strings, records, and objects.
Home-page: http://www.numpy.org
Author: Travis E. Oliphant et al.
Author-email: None
License: BSD
Location: /usr/lib/python3/dist-packages
Requires:
倒数第二个位置行应该有助于回答您的问题。
当您使用与 venv 关联的 Python 可执行文件的显式路径时,例如.venv/bin/python3 -m pip install ...
,然后 pip 将安装到虚拟环境的站点,例如.venv/lib/pythonX.Y/site-packages
。在这种情况下,是否激活venv是无关紧要的。
但是,如果您使用将在 $PATH 中解析的命令,例如 pip
,而不是明确的命令 path/to/python -m pip
,那么事情会变得复杂。
pip
等裸命令在文件系统上引用的可执行文件依赖于$PATH。在 which pip
中寻找正确的(type pip
如果有人真的很邪恶并为它取了 shell 别名)。查看 which -a pip
以查看第一个可能正在跟踪的其他人。请注意,某些 shell 会缓存命令到文件的映射,有时会搞砸它们的缓存失效(如果您看到奇怪的行为并且认为您的 shell 有搞砸了缓存)。
./pip
或 .venv/bin/pip
等命令 不会 搜索 $PATH。那是因为它里面有一个斜杠。
- 好的,您已经找到了 文件
pip
,它是一个可执行脚本。该文件的第一行称为 shebang,告诉您哪个解释器与该 pip 脚本相关联。查看 head -1 .venv/bin/pip
。如果 pip 安装到 venv 中,那么它总是匹配 venv 的 Python,假设你没有手动编辑它,因为安装程序本身会写出这个 shebang(有趣的事实:即使你直接把不同的你的源代码,安装程序重写了它!)。
pip install
会将文件放在相关解释器的系统配置中。第 1 点准确地告诉您“pip”是什么意思,第 2 点准确地告诉您“关联的解释器”是什么意思。 sysconfig 位置取决于平台。通过 运行 path/to/python -m sysconfig | grep "Paths:" --after 10
找出位置并寻找“purelib”路径。
- 不幸的是 Ubuntu 用户有一个额外的并发症!这个发行版是 Debian 的衍生版本,所以他们有一个 patched distutils installation due to Debian policies on Python packaging。 TL;DR:在 Ubuntu 上,系统站点目录将被命名为
dist-packages
,而不是系统配置报告中的 site-packages
。
“激活”一个 venv 并没有什么神奇之处,它只是设置环境变量,例如 $PATH。如果您了解 1-3 的工作原理,您就会了解激活 venv 的工作原理。
所以现在你应该能够在不猜测的情况下推理出答案:使用像 .venv/bin/pip
这样的路径与激活 venv(这改变了 $PATH,这改变了 pip
的含义,导致相同 .venv/bin/pip
) 没有区别。
附录: 为什么人们在安装 pip 时遇到这么多麻烦?
Bad hygiene. 我认为他们通过以某种方式搞乱 sys.path
搞砸了他们的系统(在启动脚本、用户站点、sitecustomize.py 中附加它,设置 PYTHONPATH
.bashrc 中的 env var,按照一些有 sudo pip install
... 可能性是无限的!)
查看pip
“脚本”,它只是一个由setuptools 写出的控制台入口点。该脚本是在安装时根据模板创建的。实际上,您不会在 pip 的源代码中的任何地方找到该文件,因为 那里不存在该文件。
#!/path/to/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.main import main # <--- look at this import statement!
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
可执行脚本做的第一件事是尝试从 pip
模块 导入其私有 API,然后 from pip
模块导入得到解析取决于 sys.path
。第一场比赛获胜。当 pip 出现随机损坏时,您应该始终问自己“这个 import 语句是否仍然找到安装程序在创建脚本时写出的相同 pip/__init__.py
文件?”
如果不是,或者 shebang 看起来不对,只需删除它并重新安装 pip。
情况: 我已经创建了一个虚拟环境并使用显式路径 运行 pip
(没有采购 activate
)。它是在全局 dist-packages
中安装软件包还是在虚拟环境的 site-packages
中安装它们。
详情:
正如 <virtualenv_name>/lib/<python_ver>/site-packages
中安装软件包。根据我的经验,当我激活 virtualenv 时,情况确实如此。我有一个现有的 bash 脚本,它直接指向 pip
可执行文件而无需激活 virtualenv。这仍然会在 virtualenv 的站点包中安装包吗?还是将它们安装在 /local/lib/<python-version>/dist-packages
?
注意:我在 Ubuntu 16.04
这在很大程度上取决于 哪个 版本(不是语义版本意义上的,而是在创建 venv 时安装的 pip 的 having-multiple-"versions" ) 您的脚本正在使用的 pip 及其配置(可能包括您的环境)。
假设您的脚本有这样一行
/some/path/to/pip install <some package>
假设pip至少安装了一个包,你可以使用
/some/path/to/pip show <that package>
它会给你如下的输出:
$ pip show numpy
Name: numpy
Version: 1.14.5
Summary: NumPy: array processing for numbers, strings, records, and objects.
Home-page: http://www.numpy.org
Author: Travis E. Oliphant et al.
Author-email: None
License: BSD
Location: /usr/lib/python3/dist-packages
Requires:
倒数第二个位置行应该有助于回答您的问题。
当您使用与 venv 关联的 Python 可执行文件的显式路径时,例如.venv/bin/python3 -m pip install ...
,然后 pip 将安装到虚拟环境的站点,例如.venv/lib/pythonX.Y/site-packages
。在这种情况下,是否激活venv是无关紧要的。
但是,如果您使用将在 $PATH 中解析的命令,例如 pip
,而不是明确的命令 path/to/python -m pip
,那么事情会变得复杂。
pip
等裸命令在文件系统上引用的可执行文件依赖于$PATH。在which pip
中寻找正确的(type pip
如果有人真的很邪恶并为它取了 shell 别名)。查看which -a pip
以查看第一个可能正在跟踪的其他人。请注意,某些 shell 会缓存命令到文件的映射,有时会搞砸它们的缓存失效(如果您看到奇怪的行为并且认为您的 shell 有搞砸了缓存)。./pip
或.venv/bin/pip
等命令 不会 搜索 $PATH。那是因为它里面有一个斜杠。- 好的,您已经找到了 文件
pip
,它是一个可执行脚本。该文件的第一行称为 shebang,告诉您哪个解释器与该 pip 脚本相关联。查看head -1 .venv/bin/pip
。如果 pip 安装到 venv 中,那么它总是匹配 venv 的 Python,假设你没有手动编辑它,因为安装程序本身会写出这个 shebang(有趣的事实:即使你直接把不同的你的源代码,安装程序重写了它!)。 pip install
会将文件放在相关解释器的系统配置中。第 1 点准确地告诉您“pip”是什么意思,第 2 点准确地告诉您“关联的解释器”是什么意思。 sysconfig 位置取决于平台。通过 运行path/to/python -m sysconfig | grep "Paths:" --after 10
找出位置并寻找“purelib”路径。- 不幸的是 Ubuntu 用户有一个额外的并发症!这个发行版是 Debian 的衍生版本,所以他们有一个 patched distutils installation due to Debian policies on Python packaging。 TL;DR:在 Ubuntu 上,系统站点目录将被命名为
dist-packages
,而不是系统配置报告中的site-packages
。
“激活”一个 venv 并没有什么神奇之处,它只是设置环境变量,例如 $PATH。如果您了解 1-3 的工作原理,您就会了解激活 venv 的工作原理。
所以现在你应该能够在不猜测的情况下推理出答案:使用像 .venv/bin/pip
这样的路径与激活 venv(这改变了 $PATH,这改变了 pip
的含义,导致相同 .venv/bin/pip
) 没有区别。
附录: 为什么人们在安装 pip 时遇到这么多麻烦?
Bad hygiene. 我认为他们通过以某种方式搞乱 sys.path
搞砸了他们的系统(在启动脚本、用户站点、sitecustomize.py 中附加它,设置 PYTHONPATH
.bashrc 中的 env var,按照一些有 sudo pip install
... 可能性是无限的!)
查看pip
“脚本”,它只是一个由setuptools 写出的控制台入口点。该脚本是在安装时根据模板创建的。实际上,您不会在 pip 的源代码中的任何地方找到该文件,因为 那里不存在该文件。
#!/path/to/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.main import main # <--- look at this import statement!
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
可执行脚本做的第一件事是尝试从 pip
模块 导入其私有 API,然后 from pip
模块导入得到解析取决于 sys.path
。第一场比赛获胜。当 pip 出现随机损坏时,您应该始终问自己“这个 import 语句是否仍然找到安装程序在创建脚本时写出的相同 pip/__init__.py
文件?”
如果不是,或者 shebang 看起来不对,只需删除它并重新安装 pip。