【问题标题】:Python requests.exceptions.SSLError: EOF occurred in violation of protocolPython requests.exceptions.SSLError: EOF 发生违反协议
【发布时间】:2016-01-29 09:05:51
【问题描述】:

我会从提供 RESTful JSON API 的 ABB G13 网关中检索一些信息。 API 由网关通过 https 端点托管。 基本认证机制用于认证。然而所有的交通 通过 SSL 层。

在 linux 上使用命令:

curl -s -k -X GET -u user:password https://host/meters/a_serial/power

一切顺利!

我正在尝试使用 Requests 2.8.1 和以下代码在 Python 2.7.10 中为 Windows 编写脚本:

import requests
requests.get('https://host/meters/a_serial/power', auth=('user', 'password'))

我有这个错误:

Traceback (most recent call last):
  File "C:/Users/mzilio/PycharmProjects/pwrgtw/test.py", line 20, in <module>
    requests.get('https://host/meters/a_serial/power', auth=('user', 'password'))
  File "C:\Python27\lib\site-packages\requests\api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Python27\lib\site-packages\requests\api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "C:\Python27\lib\site-packages\requests\adapters.py", line 433, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:590)

我已经搜索了解决方案,并尝试使用以下代码进行修复:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl

class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)

s = requests.Session()
s.mount('https://', MyAdapter())
s.get('https://host/meters/a_serial/power')

但这对我不起作用,因为我收到此错误:

Traceback (most recent call last):
  File "C:/Users/mzilio/PycharmProjects/pwrgtw/test.py", line 16, in <module>
    s.get('https://host/meters/a_serial/power')
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 480, in get
    return self.request('GET', url, **kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "C:\Python27\lib\site-packages\requests\adapters.py", line 433, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:590)

我被这个问题困住了。有人可以帮助我吗?谢谢!

【问题讨论】:

  • 参考stackoverflow问题stackoverflow.com/questions/18578439/…
  • 引用修复后,出现新错误:requests.exceptions.SSLError: ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
  • 你解决过这个问题吗?我对一个不相关的问题也有同样的看法
  • 如果互联网连接在脚本中间关闭,这不会随机发生吗?
  • 困扰了我一个星期,非常零星。我拥有所有最新的软件和 ssl 堆栈。问题是我在同一个域中有两个冲突的 DNS 条目,一个没有 A 记录。删除了那个,不得不等待 TTL 48 小时。

标签: python ssl https python-requests


【解决方案1】:

这东西对我有用,只要确定这些模块是否安装,如果没有安装它们,以下是:

pip install ndg-httpsclient

pip install pyopenssl

pip install pyasn1

它删除了我的 SSLError: EOF 发生违反协议 (_ssl.c:590) 错误。

希望对你有帮助。

【讨论】:

  • 这对我没有任何作用。
  • 你必须以某种方式使用它们,把你的工具放在篮子里,它们将如何帮助你!
  • 我投了反对票,因为它对我没有任何帮助。我猜这些库的下载统计数据无缘无故地上升了 o.o
【解决方案2】:

第 1 步:检查 Python 是否支持 TLS 1.1

您的 Python 设置可能仅支持 TLS 1.0,而不支持 TLS 1.1 或更高版本。

你可以这样检查:

Python 3

from urllib.request import urlopen
urlopen('https://www.howsmyssl.com/a/check').read()

Python 2

from urllib2 import urlopen
urlopen('https://www.howsmyssl.com/a/check').read()

(如果您收到urllib.error.URLError: &lt;urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)&gt;,您可能必须禁用证书验证。注意:这样做将禁用 SSL 保护,以防止冒充或拦截该网站流量的作恶者 - 请参阅 https://en.wikipedia.org/wiki/Man-in-the-middle_attack强> )

import ssl
urlopen('https://www.howsmyssl.com/a/check', context=ssl._create_unverified_context()).read()

检查密钥tls_version 的输出。如果它显示TLS 1.0 而不是TLS 1.1TLS 1.2,则可能是问题所在。

如果您使用的是 virtualenv,请务必在里面运行命令。

第 2 步:使用较新版本的 OpenSSL 安装 Python

为了支持 TLS 1.1 或更高版本,您可能需要安装更新版本的 OpenSSL,然后再次安装 Python。这应该会给你一个支持 TLS 1.1 的 Python。

该过程取决于您的操作系统 - 这是OS X 的指南。

virtualenv 用户
对我来说,我的 virtualenv 之外的 Python 支持 TLS 1.2,所以我只是删除了旧的 virtualenv,并使用相同的包创建了一个新的,然后它就可以工作了。轻轻松松!

【讨论】:

  • 在上面尝试过,urlopen 将 tls_version 显示为 1.2,但我仍然收到相同的错误:ssl.SSLEOFError: EOF 违反协议 (_ssl.c:579)。有关如何解决此问题的任何其他想法?
  • @Rama 在这种情况下,您可能会遇到不同的问题。就像这里提到的stackoverflow.com/a/46467942/118608 中提到的缺少的ndg-httpsclient 包一样。我只知道上面的答案(我的答案)对我有用
  • 命令行单行检查:python -c "from urllib.request import urlopen ; print(urlopen('https://www.howsmyssl.com/a/check').read())"
  • 需要什么版本的openssl?
  • @HarryMoreno 检查this SO answer。 Openssl 1.0.1 或更高版本支持 TLS 1.1。
【解决方案3】:

当它应该直接连接到服务器时,我发现它正在通过代理。

我解决了这个问题

unset https_proxy

【讨论】:

  • 你在哪里添加的?
  • 就在我的 linux 终端中 - 它会取消设置 https_proxy 环境变量。
【解决方案4】:

我遇到了完全相同的错误,原来我没有安装 ndg-httpsclient,请参阅我在 github 中提出的原始 issue

【讨论】:

  • 这种方式对我有帮助
【解决方案5】:

如果中间请求出现这个错误,可以参考https://github.com/requests/requests/issues/3391中提到的解决方案。

基本上,如果您向服务器发出大量请求并且其中一些请求遇到此问题,您可以使用Session 重试请求。

让我知道这是否有效。

【讨论】:

    【解决方案6】:

    我唯一一次看到这种性质的错误是我使用requests 筛选数据并且我使用的是多处理库。我会在没有池管理器的情况下尝试您的代码,或者将您的应用程序拆分为两个应用程序,一个分配 url,另一个使用它们。

    客户端-服务器对here 应该会给你一些想法。当我使用 hacky 服务器代码将所有 url 加载到内存中的队列中时,我能够水平扩展我的客户端,就在 app.run 之前。希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-15
      • 2016-03-11
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      相关资源
      最近更新 更多