Python requests.exceptions.SSLError:违反协议发生EOF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33410577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:19:24  来源:igfitidea点击:

Python requests.exceptions.SSLError: EOF occurred in violation of protocol

pythonsslhttpspython-requests

提问by mzilio

I would retrieve some information from an ABB G13 gateway that offer a RESTful JSON API. API is hosted by the gateway via https endpoint. Basic authentication mechanism is used for authentication. However all traffic goes through SSL layers.

我将从提供 RESTful JSON API 的 ABB G13 网关中检索一些信息。API 由网关通过 https 端点托管。使用基本认证机制进行认证。但是,所有流量都通过 SSL 层。

On linux with command:

在 linux 上使用命令:

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

All goes well!

一切顺利!

I'm trying to write a script for windows in Python 2.7.10 with Requests 2.8.1 and with this code:

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

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

I have this error:

我有这个错误:

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)

I've searched for a solution and I've tried to fix with this code:

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

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')

But it doesn't work for me cause I get this error:

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

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)

I'm stuck on this problem. Could someone help me? Thanks!

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

回答by hughdbrown

The only time I have seen errors of this nature have been times that I was using requeststo screen scrape data and I was using a multiprocessing library. I would either try your code without the pool manager or split your app into two apps, one that doles out urls and another that consumes them.

我唯一一次看到这种性质的错误是我requests用来筛选抓取数据的时候,我使用的是多处理库。我要么在没有池管理器的情况下尝试您的代码,要么将您的应用程序拆分为两个应用程序,一个分发 url,另一个使用它们。

The client-server pair hereshould give you some ideas. I was able to scale my client out horizontally when I used the hacky server code to load all urls into a Queue in memory just before app.run. Hope that helps.

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

回答by A G

I found it was going through a proxy when it should have connected to the server directly.

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

I fixed this by doing

我通过这样做解决了这个问题

unset https_proxy

回答by James Lin

I had exactly the same error, turns out that I didn't have ndg-httpsclientinstalled, see my original issueraised in github.

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

回答by varun

If you are getting this error for intermediate requests, you can refer to the solution mentioned in https://github.com/requests/requests/issues/3391.

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

Basically, if you are making a lot of requests to a server and facing this issue with some of those requests you can use Sessionto just retry the requests.

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

Let me know if this works.

让我知道这个是否奏效。

回答by giving_the_world

This thing worked for me, just make sure whether these modules are installed or not, if not then install them, following are:

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

pip install ndg-httpsclient

pip install pyopenssl

pip install pyasn1

It removed my SSLError: EOF occurred in violation of protocol (_ssl.c:590) error.

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

Hope it helps.

希望能帮助到你。

回答by qff

Step 1: Check that Python supports TLS 1.1

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

You may have a Python setup that only supports TLS 1.0 – not TLS 1.1 or above.

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

You can check it like this:

你可以这样检查:

Python 3

蟒蛇 3

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

Python 2

蟒蛇 2

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

Check the output for the key tls_version. If it says TLS 1.0and not TLS 1.1or TLS 1.2that could be the problem.

检查 key 的输出tls_version。如果它说TLS 1.0而不是,TLS 1.1或者TLS 1.2那可能是问题所在。

If you're using a virtualenv, be sure to run the command inside.

如果您使用的是 virtualenv,请确保在其中运行命令。

Step 2: Install Python with a newer version of OpenSSL

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

In order support TLS 1.1 or above, you may need to install a newer version of OpenSSL, and the install Python again afterwards. This should give you a Python that supports TLS 1.1.

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

The process depends on your operating system – here's a guide for OS X.

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

virtualenv users
For me, the Python outside of my virtualenv had TLS 1.2 support, so just I removed my old virtualenv, and created a new one with the same packages and then it worked. Easy peasy!

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