当导入Python的Docker SDK时出现ImportError: No module named ssl_match_hostname错误。

23

为了使用Python的Docker SDK,我正在尝试在Python脚本中导入docker,但结果出现了以下的ImportError

Traceback (most recent call last):
  File "/home/kurt/dev/clones8/ipercron-compose/furion/iclib/tests/test_utils/docker_utils.py", line 1, in <module>
    import docker
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/__init__.py", line 6, in <module>
    from .client import Client, AutoVersionClient, from_env # flake8: noqa
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/client.py", line 11, in <module>
    from . import api
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/api/__init__.py", line 2, in <module>
    from .build import BuildApiMixin
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/api/build.py", line 9, in <module>
    from .. import utils
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/utils/__init__.py", line 2, in <module>
    from .utils import (
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/utils/utils.py", line 19, in <module>
    from .. import tls
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/tls.py", line 5, in <module>
    from .ssladapter import ssladapter
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/ssladapter/__init__.py", line 1, in <module>
    from .ssladapter import SSLAdapter # flake8: noqa
  File "/home/kurt/.local/lib/python2.7/site-packages/docker/ssladapter/ssladapter.py", line 21, in <module>
    from backports.ssl_match_hostname import match_hostname
ImportError: No module named ssl_match_hostname
[Finished in 0.2s with exit code 1]
[shell_cmd: python -u "/home/kurt/dev/clones8/ipercron-compose/furion/iclib/tests/test_utils/docker_utils.py"]
[dir: /home/kurt/dev/clones8/ipercron-compose/furion/iclib/tests/test_utils]
[path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin]
奇怪的是,该导入语句在其他地方确实可以工作,例如在iPython提示符中:
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import docker

In [2]: 

为什么在第一种情况下导入不起作用?


你有两个版本的Python吗?你尝试在Python3中安装docker了吗?例如,pip3 install docker - Dmitry
我有两个版本的Python,但据我回忆,我没有尝试过pip3 install docker - Kurt Peek
8个回答

53

升级 Docker 并未解决我的问题。相反,我必须安装 Ubuntu 包的 backports(并从 pip 卸载):

sudo pip uninstall backports.ssl-match-hostname
sudo apt-get install python-backports.ssl-match-hostname

在 Fedora 29 中我也遇到了同样的问题,sudo dnf reinstall python2-backports-ssl_match_hostname 命令解决了它。 - Nemo
1
在RHEL7上,通过使用更新的本地安装程序来替换不稳定的系统安装程序,解决了这个问题:pip2 install --user --upgrade backports.ssl_match_hostname - fuzzyTew

8
在Ubuntu/Debian操作系统中,目前存在与软件包升级相关的错误(bug #893520),其中__init__.py文件未生成。
请检查以下文件是否存在:/usr/lib/python2.7/dist-packages/backports/__init__.py 如果该文件不存在且已安装python-backports.ssl-match-hostname软件包,则运行以下命令以生成缺失的文件:
sudo pycompile -p python-backports.ssl-match-hostname

7

我曾经在本地安装了backports.ssl-match-hostname,这导致它无法被系统级别安装。我通过以下方式解决了这个问题:

sudo pip uninstall backports.ssl-match-hostname

紧随其后
sudo pip install --upgrade docker

6
问题可能是由于Docker-compose和Docker的版本不同导致的。首先比较版本并升级以使其兼容。
其次,您可以通过pip卸载后向兼容包。
sudo pip uninstall backports.ssl-match-hostname

然后再将它作为Ubuntu软件包重新安装。

sudo apt-get install python-backports.ssl-match-hostname

0

如果您从docker-compose看到此消息:

对于我来说,@CGFoX的答案并没有起作用,尽管这是正确的方向。在分析问题时,我们发现dist-packages有两个python路径:/usr/local/lib/python2.7/dist-packages/backports/usr/lib/python2.7/dist-packages/backports

Python试图从/usr/local/lib/python2.7/dist-packages/backports加载模块“ssl_match_hostname”。但是它在那里不存在: drwxr-sr-x 5 root staff 4096 Aug 12 07:46 ./ drwxrwsr-x 130 root staff 12288 Aug 12 07:37 ../ -rw-r--r-- 1 root staff 75 Nov 14 2018 __init__.py -rw-r--r-- 1 root staff 269 Nov 14 2018 __init__.pyc drwxr-sr-x 2 root staff 4096 Nov 14 2018 configparser/ drwxr-sr-x 2 root staff 4096 Nov 14 2018 shutil_get_terminal_size/

但该模块存在于另一个位置。

x@soumubuntu:~$ ll /usr/lib/python2.7/dist-packages/backports total 16 drwxr-xr-x 3 root root 4096 Aug 12 07:19 ./ drwxr-xr-x 78 root root 4096 Aug 12 06:51 ../ -rw-r--r-- 1 root root 0 Aug 9 03:05 __init__.py -rw-r--r-- 1 root root 141 Aug 12 07:19 __init__.pyc drwxr-xr-x 2 root root 4096 Aug 12 07:19 ssl_match_hostname/

所以,我从B->A复制了它:

sudo cp -r /usr/lib/python2.7/dist-packages/backports/ssl_match_hostname/ /usr/local/lib/python2.7/dist-packages/backports/

然后,哇,docker compose现在可以工作了。


0

在修复之前,不要与其他后备软件包一起安装它(如果他们修复了它)

https://bitbucket.org/ambv/configparser/issues/17/importerror-when-used-with-other-backports#comment-36669436中看到:

Michał Górny

好吧,我只是想在这里报告核心问题,但似乎已经有人以艰苦的方式学习了它。

长话短说,您永远不能混合pkg_resources命名空间和pkgutil命名空间。这在Python打包指南中有解释。尝试导入两者可能是引起随机故障的最佳方法。您必须决定其中之一,并在使用后备命名空间的所有软件包中始终使用它。

现在,后备软件包似乎仅用于声明名称空间,并使用pkgutil。因此,我建议遵循那个软件包。


0

让我解释一下问题的根本原因。 当Python查找'backports'目录时,它会继续查找'ssl_match_hostname'子目录。如果未找到,则会出现错误。 换句话说,如果在'/usr/lib.../backports'中没有'/usr/lib.../backports/ssl_match_hostname'(通过apt安装的任何后备),则在/usr/local/lib或/home中使用pip安装任何内容都是无意义的。

如果发生发行版和pip之间的冲突:

dpkg-query -S /usr/lib/python2.7/dist-packages/backports
apt remove all_found_packages
pip install whatever_you_need

如果全局和本地pip之间发生冲突,请使用类似的技巧解决。

使用strace很方便解决这类问题。


-2

我遇到了类似的问题,但是通过先使用以下命令卸载后解决了 -

pip uninstall backports.ssl_match_hostname

成功卸载后,请使用以下命令安装docker客户端 -

pip install docker-py

希望这能帮助解决这个问题。


1
docker-py未维护。并且在使用系统软件包管理器(例如yum/dnf/...)安装的较新系统上,无法删除后向兼容包。 - sorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接