Requests: max-retries-exceeded-Ausnahmen sind verwirrend

Erstellt am 15. Feb. 2013  ·  39Kommentare  ·  Quelle: psf/requests

Hi,
zum Beispiel:

>>> requests.get('http://localhost:1111')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "requests/api.py", line 55, in get
    return request('get', url, **kwargs)
  File "requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "requests/sessions.py", line 312, in request
    resp = self.send(prep, **send_kwargs)
  File "requests/sessions.py", line 413, in send
    r = adapter.send(request, **kwargs)
  File "requests/adapters.py", line 223, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 61] Connection refused)

(vorausgesetzt, auf Port 111 lauscht nichts)

die Ausnahme sagt "Max. Wiederholungen überschritten". Ich fand das verwirrend, weil ich keine Wiederholungs-bezogenen Parameter angegeben habe. Tatsächlich kann ich keine Dokumentation über die Angabe des Wiederholungszählers finden. Nachdem Sie den Code durchgegangen sind, scheint es, dass urllib3 der zugrunde liegende Transport ist und mit max_retries=0 aufgerufen wird (es gibt also tatsächlich keine Wiederholungen). und Requests umschließt einfach die Ausnahme. es ist also verständlich, aber es verwirrt den Endbenutzer (Endentwickler)? Ich denke, hier sollte etwas besser gemacht werden, vor allem wenn man bedenkt, dass es sehr einfach ist, diesen Fehler zu bekommen.

Feature Request

Hilfreichster Kommentar

Ich stimme zu, das ist ziemlich verwirrend. Anfragen werden nie wiederholt (es setzt die Wiederholungen = 0 für den HTTPConnectionPool von urllib3), sodass der Fehler ohne HTTPConnectionPool/MaxRetryError-Zeug viel offensichtlicher wäre. Ich habe bis jetzt nicht bemerkt, dass Anfragen urllib3 verwendet haben, als ich in den Quellcode beider Bibliotheken eintauchen musste, um herauszufinden, wie viele Wiederholungen es machte:

ConnectionError(MaxRetryError("HTTPSConnectionPool(host='api.venere.com', port=443): \
    Max retries exceeded with url: /xhi-1.0/services/XHI_HotelAvail.json (\
    Caused by <class 'socket.error'>: [Errno 10054] \
    An existing connection was forcibly closed by the remote host)",),)

Idealerweise würde die Ausnahme nur so aussehen:

ConnectionError(<class 'socket.error'>: [Errno 10054] \
    An existing connection was forcibly closed by the remote host))

Alle 39 Kommentare

Requests umschließt die Ausnahme für die Benutzerfreundlichkeit. Die ursprüngliche Ausnahme ist Teil der Nachricht, obwohl der Traceback irreführend ist. Ich überlege, wie ich das verbessern kann.

Ich denke, ich brauche einen automatischen Wiederholungsversuch, um einige Fehler zu ignorieren

Ich stimme zu, das ist ziemlich verwirrend. Anfragen werden nie wiederholt (es setzt die Wiederholungen = 0 für den HTTPConnectionPool von urllib3), sodass der Fehler ohne HTTPConnectionPool/MaxRetryError-Zeug viel offensichtlicher wäre. Ich habe bis jetzt nicht bemerkt, dass Anfragen urllib3 verwendet haben, als ich in den Quellcode beider Bibliotheken eintauchen musste, um herauszufinden, wie viele Wiederholungen es machte:

ConnectionError(MaxRetryError("HTTPSConnectionPool(host='api.venere.com', port=443): \
    Max retries exceeded with url: /xhi-1.0/services/XHI_HotelAvail.json (\
    Caused by <class 'socket.error'>: [Errno 10054] \
    An existing connection was forcibly closed by the remote host)",),)

Idealerweise würde die Ausnahme nur so aussehen:

ConnectionError(<class 'socket.error'>: [Errno 10054] \
    An existing connection was forcibly closed by the remote host))

Das wäre ideal. Das Problem besteht darin, diese Ausnahmen wie wir zu umschließen. Sie sorgen für eine großartige API, aber eine schlechte Debugging-Erfahrung. Ich habe jedoch eine Idee, wie man es beheben und alle Informationen bewahren kann

Wir müssen auch den Fall berücksichtigen, in dem ein Benutzer _wiederholt_ Konfigurationsversuche ausführt. In diesem Fall ist diese Ausnahme angemessen.

@Lukasa , ich bin mir nicht sicher, ob Sie das berücksichtigen müssen - Kenneth sagte hier, dass Anfragen explizit keine Wiederholungsversuche als Teil seiner API unterstützen sollten.

Richtig, aber es gibt keine Möglichkeit, einen Benutzer daran zu hindern, dies tatsächlich zu tun.

Mein Plan, fürs Protokoll, ist, so weit wie möglich nach unten zur untersten Ausnahmeebene zu gehen und diese stattdessen zu verwenden. Das Problem mit dem Beispiel von @benhoyt besteht darin, dass die

Das Beispiel von

>>> e
ConnectionError(MaxRetryError("HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 111] Connection refused)",),)
>>> e.args
(MaxRetryError("HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 111] Connection refused)",),)
>>> e.args[0].args
("HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 111] Connection refused)",)
>>> e.args[0].args[0]
"HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 111] Connection refused)"
>>> isinstance(e.args[0].args[0], str)
True

Das Beste, was wir tun können, ist, nur die Nachricht zu verwenden, die in e.args[0].args[0] gespeichert ist, was möglicherweise auch verwirrend sein könnte, aber wahrscheinlich weniger als das, was @benhoyt gefunden hat . Wie auch immer, wir werden Fehlermeldungen nicht analysieren, um mehr oder weniger Details zu erhalten, denn das wäre einfach völliger Wahnsinn.

@sigmavirus24 , ich stimme zu, dass das Parsen von Strings in Ausnahmen eine schreckliche Idee ist. Der MaxRetryError von urllib3 stellt jedoch bereits ein reason Attribut bereit, das die zugrunde liegende Ausnahme enthält (siehe Quellcode ). So können Sie mit e.args[0].reason bekommen, was Sie wollen.

Um mit dem obigen Beispiel fortzufahren, ist e.args[0].reason eine Instanz von socket.error :

>>> requests.get('http://localhost:1111')
Traceback (most recent call last):
  ...
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 10061] No connection could be made because the target machine actively refused it)
>>> e = sys.last_value
>>> e
ConnectionError(MaxRetryError("HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 10061] No connection could be made because the target machine actively refused it)",),)
>>> e.args[0]
MaxRetryError("HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 10061] No connection could be made because the target machine actively refused it)",)
>>> e.args[0].reason
error(10061, 'No connection could be made because the target machine actively refused it')

Schöner Fang @benhoyt. Ich bin mit urllib3 nicht so vertraut, wie ich es gerne wäre.

Wenn es wirklich so aussieht, wie Sie es gezeigt haben.
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 61] Connection refused)

dann könnte ich mir wirklich keine bessere Ausnahme träumen.

@piotr-dobrogost, das Hauptproblem (für mich) war die Tatsache, dass es sich um "maximale Wiederholungen überschritten" handelt, wenn überhaupt keine Wiederholungen erforderlich sind. Zuerst dachte ich, es sei der Webdienst, den ich benutzte, und kontaktierte sie. Dann, als ich weiter grub, entdeckte ich, dass dies eine Eigenart von urllib3 war. Sie sehen also die Verwirrung.

Haben Sie (Caused by <class 'socket.error'>: [Errno 61] Connection refused) Teil der Ausnahme verpasst?

Ja, du hast recht - es ist alles da. Aber wie gesagt, das habe ich zunächst übersehen, denn der MaxRetryError ist ein Ablenkungsmanöver.

Diese Sache mit den maximalen Wiederholungen macht mich immer verrückt. Macht es irgendjemandem etwas aus, wenn ich eintauche und schaue, ob ich keine PR zusammenstellen kann, um die Wiederholungsnachricht zu zerquetschen?

Ich möchte nicht aus dem Nichts auftauchen, aber ich verwende Anfragen in der Python-Arbeit, die wir bei Cloudant leisten. Wir erhalten Seiten, die die Wiederholungssache enthalten, und das kann ein Ablenkungsmanöver sein.

Die Antwort ist _vielleicht_.

Das Problem besteht darin, dass Sie zwar standardmäßig keine Wiederholungsversuche durchführen, Sie jedoch Anfragen so konfigurieren können, dass fehlgeschlagene Anfragen automatisch wiederholt werden. In diesen Situationen ist das MaxRetryError wir verpackt haben, völlig vernünftig. Wenn Sie eine Lösung finden, die MaxRetryError an Ort und Stelle lässt, wenn es sein sollte, aber es entfernt, wenn Sie garantieren können, dass keine Wiederholungsversuche unternommen wurden, werden wir es in Betracht ziehen. =)

@Lukasa danke, ich erfrische mich hier im Backlog. Wenn ich die Chance bekomme, einzutauchen, werde ich auf jeden Fall Kontakt aufnehmen.

Es kommt mir fast so vor, als ob der richtige Ort für die Änderung in urllib3 ist? Es ist sinnvoll, MaxRetryError im Kontext automatischer Wiederholungen auszulösen, aber im Fall von Null-Wiederholungen (vielleicht die Erfahrung mit naiven Anfragen) kann es verwirrend sein.

In urllib3 scheinen die verwirrenden Fehler hier über Anfragen ausgelöst werden zu können. Es wäre fast schon nett, einen MaxRetryError nur dann auszulösen, wenn retries==0 and max_retries!=0 . Wenn stattdessen max_retries==0 ausgelöst wird, wird stattdessen ein einfacher

Ich sehe, dass urllib3, wie es von Anfragen verwendet wird, in einem enthaltenen Paket vorhanden ist - nur neugierig, warum ist das so? Wie auch immer, das waren nur ein paar Ideen, die ich da rauswerfen wollte. Ich bin immer noch dabei, die Codebasen aufzuholen.

Ob der Fix in urllib3 gehört oder nicht, liegt ganz bei @shazow. Angesichts der Tatsache, dass urllib3 standardmäßig einen Wiederholungsversuch (3-mal IIRC) durchführt, kann es sein, dass er das Verhalten von urllib3 unverändert beibehalten möchte. Pingen Sie ihn an, um seine Eingabe zu erhalten.

Wir bieten urllib3 an, um einige Abhängigkeitsprobleme zu vermeiden. Im Wesentlichen bedeutet dies, dass wir immer gegen eine bekannte Version von urllib3 arbeiten. Dies wurde in #1384 und #1812 in quälender Länge besprochen, wenn Sie die düsteren Details wollen.

Puh grob, aber informativ. @shazow Dies sind nur ein paar Gedanken, die ich hatte - einen RequestError anstelle von MaxRetryError wie oben auslösen. Wirklich, ich glaube, ich verstehe den MaxRetryError besser, nachdem ich urlopen ausgecheckt habe .

Doppelte Bearbeitung: Wirklich sogar nur ein Kwarg, damit man raise MaxRetryError(retries=0) und die Nachricht auf retries==0 ändern kann.

Wie wäre es mit einem retries=False das Wiederholungen komplett deaktiviert und immer die ursprüngliche Ausnahme anstelle von MaxRetryError auslöst?

In der Lage zu sein, zu unterscheiden, ob urlopen um keine Wiederholungen gebeten wird und ob es bei der Anzahl der Wiederholungen auf 0 heruntergezählt wird, wäre nützlich. Es ist irritierend, den MaxRetryError zu sehen, wenn Sie nicht nach Wiederholungen gefragt haben.

Wenn jemand einen Patch + Test dafür machen möchte, wäre es dankbar. :)

@shazow super , ich würde mich

\Ö/

^Ich habe mich gefragt, ob ein Patch veröffentlicht wurde? Dieses Problem scheint ein Jahr alt zu sein.

Soweit mir bekannt nicht. =)

retries=False sollte die ursprüngliche Ausnahme ab v1.9 auslösen, kein Umbruch.

@kevinburke Gedanken?

Brauche noch ein bisschen Zeit

Kevin Burke
Telefon: 925.271.7005 | zwanzigmillisekunden.com

Am Sonntag, 5. Oktober 2014 um 10:37 Uhr, Ian Cordasco [email protected]
schrieb:

@kevinburke https://github.com/kevinburke Gedanken?


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an
https://github.com/kennethreitz/requests/issues/1198#issuecomment -57945403
.

Ja, das wurde glaube ich behoben

requests.get('http://localhost:11211')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "requests/api.py", line 60, in get
    return request('get', url, **kwargs)
  File "requests/api.py", line 49, in request
    return session.request(method=method, url=url, **kwargs)
  File "requests/sessions.py", line 457, in request
    resp = self.send(prep, **send_kwargs)
  File "requests/sessions.py", line 569, in send
    r = adapter.send(request, **kwargs)
  File "requests/adapters.py", line 407, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', error(61, 'Connection refused'))

Könnten Sie mir bitte sagen, wie dies gelöst wurde, da ich auch ein Problem mit der Ablehnung der Verbindung an meinem Ende habe. In meinem Python-Skript versuche ich, den RPC-Server zu verbinden

@SiddheshS Dieses Problem wurde behoben, indem einige Ausnahmen Stack Overflow verwenden .

Ich bin auf das gleiche Problem gestoßen. es kam gelegentlich vor. wie kann ich das beheben, kann mir jemand helfen? .Danke.

Requests.Exceptions.ConnectionError: HTTPSConnectionPool(host='api.xxxx.com', port=443): Max. Wiederholungen überschritten mit URL: /v2/goods/?category=0&sort_type=2&page_size=3&page_num=13&t=0&count=110 (Verursacht) von NewConnectionError(': Fehler beim Aufbau einer neuen Verbindung: [Errno 110] Zeitüberschreitung der Verbindung',))
Traceback (letzter Anruf zuletzt):
Datei "test.py", Zeile 335, in
hauptsächlich()
Datei "test.py", Zeile 290, in main
Ergebnis = get_goods_info()
Datei "test.py", Zeile 67, in get_goods_info
result = request.get(url)
Datei "/usr/local/lib/python2.7/site-packages/requests/api.py", Zeile 69, in get
Rückgabeanforderung('get', url, params=params, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/api.py", Zeile 50, in Anfrage
Antwort = session.request(method=Methode, URL=URL, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/sessions.py", Zeile 468, in request
resp = self.send(prep, *_send_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/sessions.py", Zeile 576, in send
r = adapter.send(Anfrage, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/adapters.py", Zeile 423, in send
ConnectionError(e, request=request) erhöhen

@nkjulia Der Verbindungsversuch hat eine

Ich habe mich damit auch irregeleitet....

@kevinburke wie wurde Ihr Problem gelöst, nachdem der Fehler "Verbindung abgelehnt" wurde? Könnten Sie bitte einen Rat geben, Kumpel. TIA

Ignoriere meinen Postkollegen. Ich hatte mehrere Python-Versionen auf meinem Computer, aufgrund derer er nicht die richtige auswählen konnte und einen Fehler auslöste. Dies zu posten und zu denken, dass es für jemanden hilfreich sein könnte.

Ich bin auf das gleiche Problem gestoßen. es kam gelegentlich vor. wie kann ich das beheben, kann mir jemand helfen? .Danke.

Requests.Exceptions.ConnectionError: HTTPSConnectionPool(host='api.xxxx.com', port=443): Max. Wiederholungen überschritten mit URL: /v2/goods/?category=0&sort_type=2&page_size=3&page_num=13&t=0&count=110 (Verursacht) von NewConnectionError(': Fehler beim Aufbau einer neuen Verbindung: [Errno 110] Zeitüberschreitung der Verbindung',))
Traceback (letzter Anruf zuletzt):
Datei "test.py", Zeile 335, in
hauptsächlich()
Datei "test.py", Zeile 290, in main
Ergebnis = get_goods_info()
Datei "test.py", Zeile 67, in get_goods_info
result = request.get(url)
Datei "/usr/local/lib/python2.7/site-packages/requests/api.py", Zeile 69, in get
Rückgabeanforderung('get', url, params=params, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/api.py", Zeile 50, in Anfrage
Antwort = session.request(method=Methode, URL=URL, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/sessions.py", Zeile 468, in request
resp = self.send(prep, *_send_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/sessions.py", Zeile 576, in send
r = adapter.send(Anfrage, *_kwargs)
Datei "/usr/local/lib/python2.7/site-packages/requests/adapters.py", Zeile 423, in send
ConnectionError(e, request=request) erhöhen

Wenn dieses Problem gelöst wurde, geben Sie mir bitte einen Rat.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen