【问题标题】:Python reload pip doesn't workPython重新加载pip不起作用
【发布时间】:2017-06-06 21:51:11
【问题描述】:

我目前正在尝试升级 pip,然后在 python 脚本中安装 paramiko,因为脚本本身使用了 paramiko。下面是我想要完成的一个简单案例

import pip

try:
        import paramiko
except ImportError:
        pip.main(["install", "--upgrade", "pip"])
        reload(pip)
        pip.main(["install", "--user", "paramiko"])
        import paramiko

ssh = paramiko.SSHClient()

我正在使用 python 2.7 的 Ubuntu 16.04 VM 中运行此脚本,该 VM 没有 paramiko 和 pip 版本 8.1.1。对于运行脚本后 pip 升级的输出,我得到:

收集 pip 下载 pip-9.0.1-py2.py3-none-any.whl (1.3MB) 100% |████████████████████████████████| 1.3MB 712kB/s 安装采集包:pip 安装成功 pip-8.1.1 你正在使用 pip 版本 8.1.1,但是版本 9.0.1 可用。你应该 考虑通过“pip install --upgrade pip”命令进行升级。

之后,它尝试按预期安装 paramiko,但它失败了,因为它基本上无法安装 paramiko 使用的 Cryptography 依赖项。但是,如果它使用升级后的 pip,这将不是问题。我已将 VM 恢复到以前的快照以手动安装 paramiko,方法是

pip install --upgrade pip
pip install --user paramiko

在 shell 中它可以工作,但我需要能够在脚本中执行此操作。

注意,我还将虚拟机恢复到以前的快照,并尝试在 shell 中使用上述命令安装 paramiko,但没有先执行 pip 升级,并且正如预期的那样,我得到了与脚本在尝试时给出的相同的错误安装 paramiko。 现在我通过尝试在脚本中包含它进行了一些测试:

pip.main(["install", "--upgrade", "pip"])
reload(pip)
pip.main(["install", "--upgrade", "pip"])
reload(pip)

至于我得到的输出:

收集点
正在下载 pip-9.0.1-py2.py3-none-any.whl (1.3MB)

100% |████████████████████████████████| 1.3MB 712kB/s Installing collected packages: pip Successfully installed pip-8.1.1 You are using pip version 8.1.1, however version 9.0.1 is available. 

您应该考虑通过“pip install --upgrade pip”命令进行升级。

收集点
使用缓存的 pip-9.0.1-py2.py3-none-any.whl

安装收集的包:pip 安装成功 pip-8.1.1

您使用的是 pip 版本 8.1.1,但版本 9.0.1 可用。

您应该考虑通过“pip install --upgrade pip”命令进行升级。

注意它是如何在第二次 pip 升级时使用缓存的 pip-9.0.1 的。这是否意味着重新加载后,脚本正在使用 pip 9.0.1?如果是这样,那么为什么 paramiko 安装不使用升级的 pip?如何让 paramiko 使用升级后的 pip?

【问题讨论】:

  • 您可能需要在此之前运行sudo apt-get install build-essential libssl-dev libffi-dev python-dev -y,因为密码库需要它们。
  • 我现在正试图避免使用 sudo,因为此脚本稍后可能会在权限受到限制的 VM 上运行,而且我还试图将安装/更改的数量降至最低系统。

标签: python-2.7


【解决方案1】:

您是否尝试从 sys.modules 数组中删除 pip 包?

import pip
import sys
import site

print ('PIP Version: ' + pip.__version__)

pip.main(["install", "--upgrade", "pip"])

user_path  = site.getusersitepackages()
sytem_path = site.getsitepackages()

sys.path = [user_path] + system_path + sys.path

pips = [module for module in sys.modules if module.startswith('pip')]
for pip_module in pips:
    sys.modules.pop(pip_module)

del pip

import pip
print ('PIP Version: ' + pip.__version__)

在安装了 pip 8.1.1 的机器上运行,我得到的输出是:

 begnini@coffee-machine:~# python update.py
 PIP Version: 8.1.1
 Collecting pip
  Downloading pip-9.0.1-py2.py3-none-any.whl (1.3MB)
    100% |████████████████████████████████| 1.3MB 651kB/s
 Installing collected packages: pip
  Found existing installation: pip 8.1.1
    Uninstalling pip-8.1.1:
      Successfully uninstalled pip-8.1.1
 Successfully installed pip-9.0.1
 PIP Version: 9.0.1

编辑:就像我们讨论的那样,问题在于 pip 试图首先在主要的 python lib 目录中搜索而不是 /usr/local/lib 目录。为了解决这个问题,我在系统路径数组的第一个位置添加了本地 lib 目录。通过此修改,该错误应该得到修复。

编辑 2:添加的站点路径改为使用硬编码的目录。

【讨论】:

  • 所以,我尝试了您的解决方案,但仍然无法正常工作。我从字面上复制并粘贴了您拥有的内容,升级前的版本我有 8.1.1(预期),但升级后的版本仍然是 8.1.1。有趣的是,在脚本运行后,如果我要重新运行脚本或者只是从 shell 检查版本,我会得到 9.0.1。这就像脚本必须在更改生效之前结束。此外,在升级过程中,我的输出消息与您的不同,我没有收到“发现现有...”和“正在卸载...”。在它的地方我有“成功安装 8.1.1”。
  • 脚本是否可能只是使用过时的缓存版本或其他什么?或者只是在错误的文件夹中查找?
  • 阅读您的回复,我认为您的 pip 是用 apt 安装的,对吧(python-pip)?使用apt,pip目录为/usr/lib/python2.7/dist-packages/pip,更新后新的pip目录为/usr/lib/python2.7/dist-packages/pip。您可以确认此打印pip.__path__
  • 升级 pip 之前:['/usr/lib/python2.7/dist-packages/pip']。升级pip后:['/home/user1/.local/lib/python2.7/site-packages/pip']
  • 这是否意味着脚本不能使用新的 pip 版本,因为它在新目录中?是否可以将 pip 升级到我在脚本中指定的目录,然后以脚本将使用该目录中的 pip 的方式重新加载 pip?
【解决方案2】:

所以经过一番挖掘,看起来这是一个已修补的pip bug。不幸的是,我可能并不总是能够控制将运行此脚本的机器(即无法应用补丁),所以我的解决方案只是在第二次导入 paramiko 时使用 os.execl() 重新启动脚本,除了部分失败。

至于bug,总结一下,pip升级后,报错版本,但是pip升级了。因此,如果再次运行该脚本,则使用新版本的 pip 可以正确安装 paramiko,因此解决方案是重新启动脚本。

关于使用 os.execl() 的指导,因为 python 文档不是很清楚,请关注this link

我的代码现在的样例:

import pip
import sys
import os

try:
        import paramiko
except ImportError:
        pip.main(["install", "--upgrade", "pip"])
        pip.main(["install", "--user", "paramiko"])
        try:
            import paramiko
        except ImportError:
            os.execl(sys.executable, 'python', __file__, *sys.argv[1:])

ssh = paramiko.SSHClient()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 2012-05-31
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多