Requests: تعد استثناءات max-retries-التي تم تجاوزها مربكة

تم إنشاؤها على ١٥ فبراير ٢٠١٣  ·  39تعليقات  ·  مصدر: psf/requests

أهلا،
على سبيل المثال:

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

(بافتراض عدم سماع أي شيء على المنفذ 1111)

الاستثناء يقول "تم تجاوز الحد الأقصى لعدد مرات إعادة المحاولة". لقد وجدت هذا مربكًا لأنني لم أحدد أي معلمات متعلقة بإعادة المحاولة. في الواقع ، لا يمكنني العثور على أي وثائق حول تحديد عدد مرات إعادة المحاولة. بعد المرور عبر الكود ، يبدو أن urllib3 هو النقل الأساسي ، ويتم استدعاؤه بـ max_retries = 0 (لذلك في الواقع لا توجد عمليات إعادة محاولات). والطلبات ببساطة يلتف الاستثناء. لذلك من المفهوم ، لكنه يربك المستخدم النهائي (المطور)؟ أعتقد أنه يجب القيام بشيء أفضل هنا ، لا سيما بالنظر إلى أنه من السهل جدًا الحصول على هذا الخطأ.

Feature Request

التعليق الأكثر فائدة

أوافق على أن هذا محير للغاية. لا تعيد الطلبات المحاولة أبدًا (فهي تعيّن عمليات إعادة المحاولة = 0 لـ HTTPConnectionPool في urllib3) ، لذا سيكون الخطأ أكثر وضوحًا بدون عناصر HTTPConnectionPool / MaxRetryError. لم أدرك الطلبات التي استخدمت urllib3 حتى الآن ، عندما اضطررت إلى الغوص في الكود المصدري لكلا المكتبتين لمساعدتي في معرفة عدد المحاولات التي كان يقوم بها:

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)",),)

من الناحية المثالية ، سيبدو الاستثناء كما يلي:

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

ال 39 كومينتر

الطلبات تغلف الاستثناء لراحة المستخدمين. الاستثناء الأصلي جزء من الرسالة بالرغم من أن Traceback مضلل. سأفكر في كيفية تحسين هذا.

أعتقد أنني بحاجة إلى إعادة محاولة تلقائية لتجاهل بعض الأخطاء

أوافق على أن هذا محير للغاية. لا تعيد الطلبات المحاولة أبدًا (فهي تعيّن عمليات إعادة المحاولة = 0 لـ HTTPConnectionPool في urllib3) ، لذا سيكون الخطأ أكثر وضوحًا بدون عناصر HTTPConnectionPool / MaxRetryError. لم أدرك الطلبات التي استخدمت urllib3 حتى الآن ، عندما اضطررت إلى الغوص في الكود المصدري لكلا المكتبتين لمساعدتي في معرفة عدد المحاولات التي كان يقوم بها:

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)",),)

من الناحية المثالية ، سيبدو الاستثناء كما يلي:

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

سيكون ذلك مثاليا. تكمن المشكلة في التفاف هذه الاستثناءات كما نفعل نحن. إنهم يصنعون واجهة برمجة تطبيقات رائعة ولكن تجربة تصحيح أخطاء سيئة. لدي فكرة عن كيفية إصلاحها على الرغم من الاحتفاظ بجميع المعلومات

سنحتاج أيضًا إلى النظر في الحالة التي يقوم فيها المستخدم _does_ بتكوين عمليات إعادة المحاولة ، وفي هذه الحالة يكون هذا الاستثناء مناسبًا.

Lukasa ، لست متأكدًا من أنك بحاجة إلى التفكير في ذلك - قال كينيث هنا أن الطلبات صراحةً لا ينبغي أن تدعم عمليات إعادة المحاولة كجزء من واجهة برمجة التطبيقات الخاصة بها.

صحيح ، ولكن لا توجد طريقة لمنع المستخدم من فعل ذلك بالفعل.

خطتي ، للتسجيل ، هي اجتياز أكبر قدر ممكن إلى أسفل إلى أدنى مستوى استثناء واستخدام ذلك بدلاً من ذلك. المشكلة في مثالbenhoyt هي أنه يبدو أن استثناء خطأ المقبس غير متاح لنا. (بمجرد النظر إلى ما تم لصقه. لم أحاول إعادة إنتاجه بعد واللعب به.)

مثالgabor يجعل إعادة إنتاج هذا

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

لذا فإن أفضل ما يمكننا فعله هو استخدام الرسالة المخزنة في e.args[0].args[0] والتي من المحتمل أن تكون مربكة أيضًا ، ولكن ربما أقل من تلك التي واجهها

@ sigmavirus24 ، أوافق على أن تحليل السلسلة في الاستثناءات فكرة رهيبة. ومع ذلك ، فإن MaxRetryError في urllib3 يكشف بالفعل عن سمة reason التي تحتوي على الاستثناء الأساسي (انظر التعليمات البرمجية المصدر ). لذا يمكنك الحصول على ما تريد بـ e.args[0].reason .

إذن ، بالاستمرار في المثال أعلاه ، فإن e.args[0].reason هو مثيل 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')

لطيفة التقاطbenhoyt. أنا لست على دراية بـ urllib3 كما أود أن أكون.

إذا كان يبدو حقًا كما أظهرت أي.
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 61] Connection refused)

ثم لم أستطع أن أحلم باستثناء أفضل ، حقًا.

@ piotr-dobrogost ، كانت المشكلة الرئيسية (بالنسبة لي) هي حقيقة أنها تتحدث عن "تجاوز الحد الأقصى لإعادة المحاولة" ، عندما لا يكون هناك أي إعادة محاولة متضمنة على الإطلاق. في البداية اعتقدت أنها خدمة الويب التي كنت أستخدمها لأقول ذلك ، لذلك اتصلت بهم. بعد ذلك ، اكتشفت أن هذا كان غرابة في urllib3. حتى تتمكن من رؤية الارتباك.

هل فاتتك جزء (Caused by <class 'socket.error'>: [Errno 61] Connection refused) من الاستثناء؟

نعم ، أنت على حق - كل شيء هناك. لكن كما ذكرت ، فاتني ذلك في البداية ، لأن MaxRetryError هو خداع أحمر.

هذا الشيء الذي يعيد المحاولة يدفعني دائمًا إلى الجنون. هل يمانع أي شخص إذا غصت وأرى ما إذا كان لا يمكنني وضع علاقات عامة معًا لسحق رسالة إعادة المحاولة؟

لا أقصد الظهور من العدم ، لكني أستخدم طلبات كثيرة في عمل Python الذي نقوم به في Cloudant. نحصل على صفحات تتضمن الشيء الذي يعيد المحاولة ، ويمكن أن يكون هذا الأمر خداعًا.

الجواب هو _ربما_.

تكمن المشكلة في أنه على الرغم من أننا لا نجري أي عمليات إعادة محاولات بشكل افتراضي ، إلا أنه يمكنك تكوين الطلبات لإعادة محاولة الطلبات الفاشلة تلقائيًا. في هذه المواقف ، فإن MaxRetryError الذي غلفناه معقول تمامًا. إذا كان بإمكانك التوصل إلى حل يترك MaxRetryError في مكانه عندما يجب أن يكون ، لكنه يزيله عندما يمكنك ضمان عدم إجراء أي محاولات لإعادة المحاولة ، فسننظر فيه. =)

Lukasa شكرًا ، أنا أنعش نفسي على التراكم هنا. إذا سنحت لي الفرصة للغوص ، فسوف أتواصل بالتأكيد.

يبدو لي كما لو أن المكان المناسب للتغيير في urllib3؟ من المنطقي رفع MaxRetryError في سياق عمليات إعادة المحاولة التلقائية ، ولكن في حالة عدم إعادة المحاولة (ربما تجربة الطلبات الساذجة) يمكن أن يكون الأمر محيرًا.

في urllib3 ، يبدو أنه يمكن تشغيل الأخطاء المربكة هنا عبر الطلبات. سيكون من الجيد تقريبًا رفع MaxRetryError فقط عند retries==0 and max_retries!=0 . إذا رفع max_retries==0 بدلاً من ذلك ، تم رفع خطأ RequestError عاديًا بدلاً من ذلك.

أرى أن urllib3 كما هو مستخدم في الطلبات موجود في حزمة مضمنة - فقط فضولي ، لماذا هذا؟ على أي حال ، كانت هذه مجرد أفكار قليلة أردت طرحها هناك. ما زلت ألحق بالقواعد البرمجية.

ما إذا كان الإصلاح ينتمي إلى urllib3 أم لا يعود إلى @ shazow. بالنظر إلى أن urllib3 افتراضيًا _ يعيد المحاولة (3 مرات IIRC) ، فقد يكون السبب هو أنه يريد الحفاظ على سلوك urllib3 كما هو. أزعجه للحصول على مدخلاته.

نحن نبيع urllib3 لتجنب بعض مشكلات التبعية. بشكل أساسي ، هذا يعني أننا نعمل دائمًا ضد إصدار معروف من urllib3. نوقش هذا في الطول المؤلم في # 1384 و # 1812 إذا كنت تريد التفاصيل الدقيقة.

تفو شجاعة ولكنها غنية بالمعلومات. @ shazow هذه مجرد أفكار قليلة لدي - رفع RequestError بدلاً من MaxRetryError كما هو مذكور أعلاه. أعتقد حقًا أنني أفهم MaxRetryError بشكل أفضل بعد التحقق من urlopen .

تحرير مزدوج: في الحقيقة مجرد kwarg حتى يمكن للمرء raise MaxRetryError(retries=0) وتغيير الرسالة على retries==0 .

ماذا عن retries=False الذي سيعطل عمليات إعادة المحاولة تمامًا ويرفع دائمًا الاستثناء الأصلي بدلاً من MaxRetryError ؟

من المفيد أن تكون قادرًا على التمييز بين طلب urlopen لعدم إعادة المحاولة وجعله يعد تنازليًا حتى 0 على عدد مرات إعادة المحاولة. من المزعج رؤية MaxRetryError عندما لم تطلب إعادة المحاولة.

إذا رغب أي شخص في إجراء اختبار التصحيح لهذا ، فسيكون موضع تقدير. :)

@ shazow رائع ، سأكون لعبة إذا كان بإمكاني العثور على الدورات. سأقوم باختبار الاتصال إذا كان لدي أي شيء.

\ س /

^ كنت أتساءل عما إذا كان هناك أي تصحيح تم إصداره؟ يبدو أن هذه المشكلة عمرها عام.

ليس بقدر علمي. =)

retries=False برفع الاستثناء الأصلي بدءًا من الإصدار 1.9 ، بدون التفاف.

@ kevinburke الأفكار؟

بحاجة الى مزيد من الوقت

كيفن بيرك
الهاتف: 925.271.7005 | twentymilliseconds.com

الأحد، 5 أكتوبر 2014 في 10:37، إيان Cordasco [email protected]
كتب:

kevinburke https://github.com/kevinburke الأفكار؟

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/kennethreitz/requests/issues/1198#issuecomment -57945403
.

نعم ، لقد تم إصلاح هذا على ما أعتقد

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

هل يمكن أن تخبرني من فضلك كيف تم حل ذلك ، لأنني أتلقى أيضًا مشكلة رفض الاتصال في نهايتي. في برنامج Python النصي الخاص بي ، أحاول الاتصال بخادم RPC

SiddheshS تم إصلاح هذه المشكلة عن طريق إعادة صياغة بعض الاستثناءات: لا علاقة لها بخطأ رفض الاتصال الفعلي. لطلب المساعدة في مشكلة ما ، يجب أن تفكر في استخدام Stack Overflow .

أنا واجهت نفس المشكلة . حدث ذلك من حين لآخر. كيف تصلح ، هل هناك أي شخص يمكنه مساعدتي؟ .شكرا.

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'api.xxxx.com'، port = 443): تم تجاوز الحد الأقصى لإعادة المحاولة بعنوان url: / v2 / Goods /؟ category = 0 & sort_type = 2 & page_size = 3 & page_num = 13 & t = 0 & count = 110 (سبب بواسطة NewConnectionError (': فشل إنشاء اتصال جديد: [Errno 110] انتهت مهلة الاتصال '،))
Traceback (آخر مكالمة أخيرة):
ملف "test.py" ، السطر 335 ، بتنسيق
الأساسية()
ملف "test.py" ، السطر 290 ، بشكل رئيسي
النتيجة = get_goods_info ()
ملف "test.py" ، السطر 67 ، في get_goods_info
النتيجة = request.get (url)
ملف "/usr/local/lib/python2.7/site-packages/requests/api.py" ، السطر 69 ، في get
طلب الإرجاع ('get' ، url ، params = params ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/api.py" ، السطر 50 ، في الطلب
response = session.request (الطريقة = الطريقة ، url = url ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/sessions.py" ، السطر 468 ، في الطلب
Resp = self.send (الإعدادية ، * _send_kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/sessions.py" ، السطر 576 ، في الإرسال
r = adapter.send (طلب ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/adapters.py" ، السطر 423 ، في الإرسال
رفع خطأ الاتصال (البريد ، الطلب = الطلب)

nkjulia انتهت

أنا أيضًا أضللت بهذا ....

kevinburke كيف تم حل مشكلتك بعد الحصول على خطأ رفض الاتصال؟ هل يمكنك من فضلك نصح صديقي. TIA

تجاهل منصبي يا صديقي. كان لدي إصدار متعدد من الثعابين في جهازي بسبب عدم تمكنه من اختيار النوع الصحيح وكان يرمي بالخطأ. نشر هذا التفكير قد يكون مفيدًا لشخص ما.

أنا واجهت نفس المشكلة . حدث ذلك من حين لآخر. كيف تصلح ، هل هناك أي شخص يمكنه مساعدتي؟ .شكرا.

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'api.xxxx.com'، port = 443): تم تجاوز الحد الأقصى لإعادة المحاولة بعنوان url: / v2 / Goods /؟ category = 0 & sort_type = 2 & page_size = 3 & page_num = 13 & t = 0 & count = 110 (سبب بواسطة NewConnectionError (': فشل إنشاء اتصال جديد: [Errno 110] انتهت مهلة الاتصال '،))
Traceback (آخر مكالمة أخيرة):
ملف "test.py" ، السطر 335 ، بتنسيق
الأساسية()
ملف "test.py" ، السطر 290 ، بشكل رئيسي
النتيجة = get_goods_info ()
ملف "test.py" ، السطر 67 ، في get_goods_info
النتيجة = request.get (url)
ملف "/usr/local/lib/python2.7/site-packages/requests/api.py" ، السطر 69 ، في get
طلب الإرجاع ('get' ، url ، params = params ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/api.py" ، السطر 50 ، في الطلب
response = session.request (الطريقة = الطريقة ، url = url ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/sessions.py" ، السطر 468 ، في الطلب
Resp = self.send (الإعدادية ، * _send_kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/sessions.py" ، السطر 576 ، في الإرسال
r = adapter.send (طلب ، * _kwargs)
ملف "/usr/local/lib/python2.7/site-packages/requests/adapters.py" ، السطر 423 ، في الإرسال
رفع خطأ الاتصال (البريد ، الطلب = الطلب)

إذا تم حل هذه المشكلة ، فيرجى إعطائي بعض النصائح.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات