sammchardy / python-binance

Binance Exchange API python implementation for automated trading
https://python-binance.readthedocs.io/en/latest/
MIT License
5.89k stars 2.2k forks source link

ConnectionResetError: [WinError 10054] <> client.get_klines() #660

Open veeeeens opened 3 years ago

veeeeens commented 3 years ago

Describe the bug hello I use the function client.get_klines() to update the data on the different BINANCE pairs. Everything works fine most of the time, but sometimes I don't know why I get this error:

Traceback (most recent call last): File "C:\Users\vince\AppData\Roaming\Python\Python39\site-packages\urllib3\response.py", line 438, in _error_catcher yield File "C:\Users\vince\AppData\Roaming\Python\Python39\site-packages\urllib3\response.py", line 519, in read data = self._fp.read(amt) if not fp_closed else b"" File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 458, in read n = self.readinto(b) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 502, in readinto n = self.fp.readinto(b) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\socket.py", line 704, in readinto return self._sock.recv_into(b) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1241, in recv_into return self.read(nbytes, buffer) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1099, in read return self._sslobj.read(len, buffer) ConnectionResetError: [WinError 10054] Une connexion existante a dû être fermée par l’hôte distant

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 753, in generate for chunk in self.raw.stream(chunk_size, decode_content=True): File "C:\Users\vince\AppData\Roaming\Python\Python39\site-packages\urllib3\response.py", line 576, in stream data = self.read(amt=amt, decode_content=decode_content) File "C:\Users\vince\AppData\Roaming\Python\Python39\site-packages\urllib3\response.py", line 541, in read raise IncompleteRead(self._fp_bytes_read, self.length_remaining) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\contextlib.py", line 135, in exit self.gen.throw(type, value, traceback) File "C:\Users\vince\AppData\Roaming\Python\Python39\site-packages\urllib3\response.py", line 455, in _error_catcher raise ProtocolError("Connection broken: %r" % e, e) urllib3.exceptions.ProtocolError: ("Connection broken: ConnectionResetError(10054, 'Une connexion existante a dû être fermée par l’hôte distant', None, 10054, None)", ConnectionResetError(10054, 'Une connexion existante a dû être fermée par l’hôte distant', None, 10054, None))

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Users\vince\Documents\Trading BOT v3\analyse.py", line 135, in analyse_top_param() File "C:\Users\vince\Documents\Trading BOT v3\analyse.py", line 109, in analyse_top_param df_doc = get_df_doc(paire, get_bougie_debut_analyse()) File "C:\Users\vince\Documents\Trading BOT v3\maj.py", line 86, in get_df_doc klines = client.get_klines(symbol=paire, startTime=debut_extraction, interval='1m', limit=1000) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\binance\client.py", line 734, in get_klines return self._get('klines', data=params, version=self.PRIVATE_API_VERSION) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\binance\client.py", line 237, in _get return self._request_api('get', path, signed, version, kwargs) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\binance\client.py", line 202, in _request_api return self._request(method, uri, signed, kwargs) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\binance\client.py", line 196, in _request self.response = getattr(self.session, method)(uri, kwargs) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py", line 555, in get return self.request('GET', url, kwargs) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py", line 542, in request resp = self.send(prep, **send_kwargs) File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py", line 697, in send r.content File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 831, in content self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b'' File "C:\Users\vince\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 756, in generate raise ChunkedEncodingError(e) requests.exceptions.ChunkedEncodingError: ("Connection broken: ConnectionResetError(10054, 'Une connexion existante a dû être fermée par l’hôte distant', None, 10054, None)", ConnectionResetError(10054, 'Une connexion existante a dû être fermée par l’hôte distant', None, 10054, None))

I added a counter that allows to wait one second every three calls as recommended in the get_historical_klines() function:

def get_df_doc(paire, debut_extraction=get_bougie_debut_analyse()):
    """
    permet d'obtenir un dataframe indexé sur les dates qui contient les colonnes open, close
    les lignes dont le volume est nul sont supprimées (formatage tradingview)
    :param paire: paire dont on veut récupérer les données
    :param debut_extraction: date à partir de laquelle on veut récupérer les données
    :return: un dataframe indexé sur les dates qui contient les colonnes open, close
    """
    # converti la date de début d'extraction en format UNIX milli
    debut_extraction = date_to_milli(debut_extraction)

    # création d'un client binance sans clé API
    client = get_client_without_keys()
    if client is None:
        return

    # création d'une liste vide qui servira à stocker les bougies
    data_docv = []
    # fixe la valeur initiale de la variable len_klines à 1000
    len_klines = 1000
    # initialisation d'un compteur qui permettra d'attendre une seconde tous les 3 appels
    compteur = 0
    while len_klines == 1000:
        # récupération de 1000 klines à partir de la date de début d'extraction
        klines = client.get_klines(symbol=paire, startTime=debut_extraction, interval='1m', limit=1000)
        # pour chaque kline, ne conserve que les valeurs date, open, close, volume
        klines = [[line[0], line[1], line[4], line[5]] for line in klines]
        # stock le nombre de klines dans la variable len_klines
        len_klines = len(klines)
        # len_klines est supérieur à zéro et donc que de nouvelles bougies ont été récupérées
        if len_klines > 0:
            # incrémente le compteur
            compteur += 1
            # ajoute les nouvelles bougies récupérées à la liste data_doc
            data_docv.extend(klines)
            # fixe la date de début d'extraction à la prochaine bougie
            debut_extraction = klines[-1][0] + 60000
            # si le compteur est un multiple de 3 attend une seconde
            if compteur % 3 == 0:
                time.sleep(1)

I'm still a beginner in programming, I thought I would lock the call of the get_klines() function in a try except block, and restart the client in case of an error like this :

        tentatives = 3
        while tentatives > 0:
            try:
                klines = client.get_klines(symbol=paire, startTime=debut_extraction, interval='1m', limit=1000)
            except Exception as exc:
                print(f'échec de la mise à jour de la paire {paire}')
                print("exception de type ", exc.__class__)
                print("message", exc)
                tentatives -= 1
                time.sleep(60)
                client = Client("", "")
                continue
            else:
                break

what do you think about it ? I would like that the error doesn't happen again or if it happens again that it doesn't crash the whole update...

thank you in advance

Environment (please complete the following information):

uneasyguy commented 3 years ago

https://gist.github.com/uneasyguy/efb826b9cab93471109cf35f6a45b95b

This is a pretty basic example of something you might do to reconnect following this exception.

It is a known issue and further information can be found here: https://github.com/sammchardy/python-binance/issues/389

veeeeens commented 3 years ago

Hello and thank you very much for your answer, I will take the time to look at the track that you propose to me, I wish you a pleasant day.

hammerjoe commented 2 years ago

I am also having the same problem. Is it possible to reduce the ttl of the client? Or what other solution would work? If I try to call client = Client(api_key, api_secret) I get an error.

thebigrich commented 2 years ago

I also got this type of error immediately i ran this part of my code: client = Client(api_key, api_secret). can anyone help

Karlheinzniebuhr commented 1 year ago

Same issue, any solutions? Win 10 Python 3.9 python-binance latest version

RuntimeWarning: Enable tracemalloc to get the object allocation traceback
SLAYER ETHUSDT: Orderbook exception: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None)) after 2203 seconds, Fill=False
Next run in 23 hours 22 minutes 56 seconds
ysalihtuncel commented 2 months ago

same here