繁体   English   中英

&#39;python -m pip install 之间的区别<package-name> &#39; 和 &#39;pip 安装<package-name> &#39;

[英]Difference between 'python -m pip install <package-name>' and 'pip install <package-name>'

我遇到了一个问题,我试图在虚拟环境中运行 Django 应用程序,但它一直向我显示有关缺少需要安装的软件包的错误,尽管我之前确实使用pip install <package-name>安装了它们。

在我使用python -m pip install <package-name>安装丢失的包之前,这些问题无法解决。

我的问题是这两个命令有什么区别? 其中一个命令是否将软件包安装到虚拟环境,另一个是全局安装? 我糊涂了。

旁注:此外,运行pip freeze显示的已安装包与运行python -m pip freeze时显示的包不同。


更新 1:

运行pip list -v显示使用pip install <package-name>位于lib/python3.8/site-packages目录下的虚拟环境文件夹中,而运行python -m pip list -v显示包使用python -m pip <package-name>文件位于/usr/lib/<python3 or python3.8>/<site-packages or dist-packages>目录下。


更新 2:

我使用运行 Ubuntu 20.04 64 位的 VPS 体验了上述所有内容。 奇怪的是,当我在运行 Linux Mint 的本地机器上时,执行这两个命令的作用完全相同, pip install <package-name>python -m pip install <package-name>之间没有区别python -m pip install <package-name>在我的本地机器上。


更新 3:

我所做的是删除了我的虚拟环境并在同一目录中创建了一个具有相同名称的新环境。 为了使事情更清楚,以下屏幕截图展示了我面临的问题:

1- 下面的截图显示了pip list -v全局运行时的结果: 在此处输入图片说明

2- 下面的屏幕截图显示了python -m pip list -v在全局运行时的结果: 在此处输入图片说明

上面 2 个屏幕截图显示了相同的结果(两个命令都是全局执行的,没有活动的虚拟环境)。

3- 下面的屏幕截图显示了我在虚拟环境中运行pip list -v的结果:

在此处输入图片说明

4- 下面的屏幕截图显示了在我的虚拟环境中运行python -m pip list -v的结果:

在此处输入图片说明

以上 2 个屏幕截图显示了不同的结果(两个命令都是在激活虚拟环境时执行的)。

尽管我创建了一个新的虚拟环境,但问题仍然存在。

通常没有区别。

python -m标志允许您运行特定模块。 例如,您可以运行python -m http.server在当前目录中启动一个简单的服务器。

Python 包含一个“脚本”目录。 根据您的系统设置, scripts目录中的模块可以直接从 shell 运行,无需python -m前缀。 例如,通常您直接从 shell 运行black

但是,您可能不想信任直接从 shell 运行 python 模块的原因有多种,包括:

  • 运行特定的 python 版本。 你可以做py -3.6 -m pip install something来指定一个python版本
  • 无论出于何种原因,您都不想将脚本文件夹添加到 PATH 中。 可能是因为某些名称与您计算机上的其他程序冲突。

在 virtualenv 中,这两个命令通常会做同样的事情,因为virtualenv会正确设置你的 PATH

欢迎来到符号链接、使用PATH二进制可发现性和 shebang #!/... (*nix) 的世界。

在深入了解这一切之前,让我们先谈谈pip是什么:

pip既是一个 python 模块(即python -m pip-m表示模块))又是一个二进制$ pip pip作为二进制文件(程序)是可选的,它不是必需的。 pip作为模块(在安装了所有 python 模块的site-packages内)是绝对需要的! 没有它什么都不会工作,或者更糟糕的是,你会使用你安装的另一个python版本的pip模块,然后你真的会用头撞墙......

路径变量

echo $PATH (*nix) 将显示如下内容:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

这意味着系统将通过终端首先在/usr/local/bin查找二进制文件,然后在/usr/bin查找......等等。 如果它一开始就找到了它,那就太好了,它完成了,无需继续寻找。 您可以在不同的目录中使用相同的二进制名称, PATH的顺序很重要,第二个永远不会被执行,永远。

我为什么要提到这个? 好吧,假设您安装了多个版本的pythonpip ,并且将其安装在错误的位置? 顺序错在哪里? 那个二进制文件不会按预期运行。

符号链接

您可以拥有不同版本的pippython它们彼此独立,这意味着仅仅因为您使用的是 3.8 版的python ,并不意味着您的pip指向相同的 python 二进制文件。

检查的快速方法是:(这适用于pip

$ ls -ls $(which python)
0 lrwxr-xr-x  1 root  wheel  75 Jan  1  2020 /usr/bin/python -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

您可以看到它正在使用python的系统版本,如果我只运行python ,我将忽略我拥有的任何其他版本,我可以通过指定版本号(例如python3.8 ...

您可以通过首先弄清楚您可以使用哪些二进制文件来解决这个问题:

$ echo $PATH | sed 's/:/ /g' | xargs -n1 -I{} find {} -name 'python*' | grep -v 'config$'
/usr/local/bin/python3
/usr/local/bin/python3.9
/usr/local/bin/python3.8
/usr/bin/python3
/usr/bin/python
/usr/bin/python2
/usr/bin/pythonw
/usr/bin/pythonw2.7
/usr/bin/python2.7

假设我希望我的默认pythonpython3.8 ,然后执行:

$ ln -s /usr/local/bin/python3.8 /usr/local/bin/python
$ hash -r

hash -r告诉终端忘记它之前找到的所有banaries,否则你的新符号链接将不起作用

问:为什么不直接覆盖它?

聪明的你可能会问,如果默认的python是在/usr/bin/python为什么不直接使用覆盖它呢?

$ ln -sf /usr/local/bin/python3.8 /usr/bin/python

/usr/bin/是受保护的,并且乱用系统首选项是不好的形式。 最好不要碰它, /usr/local/bin是你(机器的用户)可以乱动的。

Shebang #!/...

在大多数情况下,您会发现pip二进制文件(顺便说一下,这只是纯文本)以这样的方式开始:

#!/usr/bin/env python

或者

#!/usr/local/bin/python3.9

这表示,我是一个需要使用以下可执行文件运行的文本文件。 在第一个示例中,它使用系统来确定二进制python的方式与您在终端中找到它的方式相同,请参阅上面的PATH变量。 第二个示例是系统要使用的二进制文件的直接路径。

记住pip是一个模块,二进制pip字面意思是这样的:(这是稍微修改以使其尽可能基本并说明一点)

#!/usr/bin/env python
import sys
from pip._internal.cli.main import main
sys.exit(main())
  1. 使用python二进制文件
  2. 导入后面要用到的sys模块...
  3. pip模块导入main函数
  4. 运行main ,它返回的任何代码都将它传递给sys.exit(..)通常会返回0但这里或那里都更近了..仅供参考

当您需要定义需要将软件包安装到哪个 python 版本时,它非常方便(对不起,我的英语不好)。 比如说,你有 python3.8 和 python3.10。 你可以做python3.8 -m pip install djangopython3.10 -m pip install django

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM