web-dev-qa-db-fra.com

Python requests.exceptions.SSLError: EOF s'est produite en violation du protocole

Je voudrais récupérer des informations d'une passerelle ABB G13 offrant une API JSON RESTful. L'API est hébergée par la passerelle via https endpoint . Le mécanisme d'authentification de base est utilisé pour l'authentification. Cependant, tout le trafic Passe par des couches SSL.

Sur Linux avec la commande:

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

Tout va bien!

J'essaie d'écrire un script pour Windows dans Python 2.7.10 avec les requêtes 2.8.1 et avec ce code:

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

J'ai cette erreur:

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)

J'ai cherché une solution et j'ai essayé de corriger avec ce 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')

Mais cela ne fonctionne pas pour moi car je reçois cette erreur:

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)

Je suis coincé sur ce problème. Quelqu'un pourrait-il m'aider? Merci!

6
mzilio

Cette chose a fonctionné pour moi, assurez-vous simplement que ces modules sont installés ou non, sinon installez-les, procédez comme suit:

pip install ndg-httpsclient

pip install pyopenssl

pip install pyasn1

Il a supprimé mon erreur SSLError: EOF s'est produite en violation d'une erreur de protocole (_ssl.c: 590).

J'espère que ça aide.

8
giving_the_world

J'ai eu exactement la même erreur, il s'avère que je n'avais pas installé ndg-httpsclients, voir mon issue original dans github.

3
James Lin

J'ai trouvé qu'il passait par un proxy alors qu'il aurait dû se connecter directement au serveur.

J'ai corrigé cela en faisant

unset https_proxy
2
A G

Étape 1: Vérifiez que Python prend en charge TLS 1.1.

Vous pouvez avoir une configuration Python qui ne supporte que TLS 1.0 - pas TLS 1.1 ou supérieur.

Vous pouvez le vérifier comme ceci:

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

Vérifiez la sortie pour la clé tls_version. Si cela indique TLS 1.0 et non pas TLS 1.1 ou TLS 1.2, cela pourrait être le problème.

Si vous utilisez virtualenv, veillez à exécuter la commande à l'intérieur.

Étape 2: Installez Python avec une version plus récente d'OpenSSL

Pour prendre en charge TLS 1.1 ou une version ultérieure, vous devrez peut-être installer une version plus récente d'OpenSSL, puis installer à nouveau Python. Cela devrait vous donner un Python qui supporte TLS 1.1.

Le processus dépend de votre système d'exploitation - voici un guide pour OS X .

utilisateurs virtuels
En dehors de mon virtualenv, le python bénéficiait du support de TLS 1.2, alors je viens de retirer mon ancien virtualenv et d'en créer un nouveau avec les mêmes packages, puis tout fonctionnait. Peasy facile!

1
qff

Si vous obtenez cette erreur pour des demandes intermédiaires, vous pouvez vous reporter à la solution mentionnée dans https://github.com/requests/requests/issues/3391 .

Fondamentalement, si vous faites beaucoup de demandes à un serveur et que vous rencontrez ce problème avec certaines de ces demandes, vous pouvez utiliser Session pour simplement réessayer les demandes. 

Laissez-moi savoir si cela fonctionne.

1
varun

La seule fois où j'ai vu des erreurs de cette nature a été celle où j’utilisais requests pour filtrer les données de scrap et j’utilisais une bibliothèque de multitraitement. Je voudrais soit essayer votre code sans le gestionnaire de pool, soit scinder votre application en deux applications, l'une qui distribue les URL et l'autre qui les consomme.

Le couple client/serveur ici devrait vous donner quelques idées. J'ai été en mesure de faire évoluer mon client horizontalement lorsque j'ai utilisé le code serveur hacky pour charger toutes les URL dans une file d'attente en mémoire juste avant le app.run. J'espère que cela pourra aider.

0
hughdbrown