Requests: pengecualian max-retries-exceeded membingungkan

Dibuat pada 15 Feb 2013  ·  39Komentar  ·  Sumber: psf/requests

Hai,
Misalnya:

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

(dengan asumsi tidak ada yang mendengarkan pada port 1111)

pengecualian mengatakan "Maks. percobaan ulang terlampaui". saya menemukan ini membingungkan karena saya tidak menentukan params terkait coba lagi. sebenarnya, saya tidak dapat menemukan dokumentasi apa pun tentang menentukan penghitungan ulang. setelah melalui kode, tampaknya urllib3 adalah transportasi yang mendasarinya, dan itu disebut dengan max_retries=0 (jadi sebenarnya tidak ada percobaan ulang). dan permintaan hanya membungkus pengecualian. jadi bisa dimengerti, tapi membingungkan pengguna akhir (end-developer)? saya pikir sesuatu yang lebih baik harus dilakukan di sini, terutama mengingat sangat mudah untuk mendapatkan kesalahan ini.

Feature Request

Komentar yang paling membantu

Saya setuju ini cukup membingungkan. Permintaan tidak pernah mencoba lagi (ini menetapkan retries=0 untuk HTTPConnectionPool urllib3), jadi kesalahannya akan jauh lebih jelas tanpa hal-hal HTTPConnectionPool/MaxRetryError. Saya tidak menyadari permintaan menggunakan urllib3 sampai sekarang, ketika saya harus menyelami kode sumber kedua perpustakaan untuk membantu saya mengetahui berapa banyak percobaan yang dilakukan:

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

Idealnya pengecualian hanya akan terlihat seperti ini:

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

Semua 39 komentar

Permintaan membungkus pengecualian untuk kenyamanan pengguna. Pengecualian asli adalah bagian dari pesan meskipun Traceback menyesatkan. Saya akan memikirkan cara meningkatkan ini.

Saya pikir perlu coba ulang otomatis untuk mengabaikan beberapa kesalahan

Saya setuju ini cukup membingungkan. Permintaan tidak pernah mencoba lagi (ini menetapkan retries=0 untuk HTTPConnectionPool urllib3), jadi kesalahannya akan jauh lebih jelas tanpa hal-hal HTTPConnectionPool/MaxRetryError. Saya tidak menyadari permintaan menggunakan urllib3 sampai sekarang, ketika saya harus menyelami kode sumber kedua perpustakaan untuk membantu saya mengetahui berapa banyak percobaan yang dilakukan:

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

Idealnya pengecualian hanya akan terlihat seperti ini:

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

Itu akan ideal. Masalahnya adalah dengan membungkus pengecualian ini seperti yang kita lakukan. Mereka membuat API yang hebat tetapi pengalaman debugging yang buruk. Saya punya ide untuk memperbaikinya dan menyimpan semua informasi

Kami juga perlu mempertimbangkan kasus di mana pengguna _melakukan_ konfigurasi ulang, dalam hal ini pengecualian ini sesuai.

@Lukasa , saya tidak yakin Anda perlu mempertimbangkan itu -- Kenneth mengatakan di sini bahwa Permintaan secara eksplisit tidak boleh mendukung percobaan ulang sebagai bagian dari API-nya.

Benar, tetapi tidak ada cara untuk mencegah pengguna benar-benar melakukannya.

Rencana saya, sebagai catatan, adalah melintasi sejauh mungkin ke bawah ke pengecualian tingkat terendah dan menggunakannya sebagai gantinya. Masalah dengan contoh @benhoyt adalah sepertinya pengecualian kesalahan soket tidak tersedia untuk kami. (Hanya dengan melihat apa yang dia tempel. Saya belum mencoba mereproduksi dan memainkannya.)

Contoh @gabor sebenarnya membuat ini mudah untuk direproduksi. Menangkap pengecualian yang muncul, saya melakukan hal berikut:

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

Jadi yang terbaik yang bisa kami lakukan adalah hanya menggunakan pesan yang disimpan di e.args[0].args[0] yang juga berpotensi membingungkan, tetapi mungkin kurang dari apa yang ditemui @benhoyt . Either way, kami tidak akan mengurai pesan kesalahan untuk mencoba mendapatkan lebih banyak atau lebih sedikit detail karena itu hanya akan menjadi kegilaan total.

@ sigmavirus24 , saya setuju penguraian string dalam pengecualian adalah ide yang buruk. Namun, MaxRetryError urllib3 sudah memperlihatkan atribut reason yang berisi pengecualian yang mendasarinya (lihat kode sumber ). Jadi Anda bisa mendapatkan apa yang Anda inginkan dengan e.args[0].reason .

Jadi melanjutkan contoh di atas, e.args[0].reason adalah turunan dari 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')

Tangkapan yang bagus @benhoyt. Saya tidak terbiasa dengan urllib3 seperti yang saya inginkan.

Jika itu benar-benar terlihat seperti yang Anda tunjukkan yaitu.
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=1111): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 61] Connection refused)

maka saya tidak bisa memimpikan pengecualian yang lebih baik, sungguh.

@ piotr-dobrogost, masalah utama (bagi saya) adalah kenyataan bahwa ia berbicara tentang "max retries terlampaui", ketika tidak ada retry yang terlibat sama sekali. Awalnya saya pikir itu adalah layanan web yang saya gunakan yang mengatakan itu, jadi saya menghubungi mereka. Kemudian, menggali lebih jauh, saya menemukan ini adalah kekhasan urllib3. Jadi Anda bisa melihat kebingungannya.

Apakah Anda melewatkan (Caused by <class 'socket.error'>: [Errno 61] Connection refused) bagian dari pengecualian?

Ya, Anda benar -- semuanya ada di sana. Tapi seperti yang saya sebutkan, saya melewatkannya pada awalnya, karena MaxRetryError adalah ikan haring merah.

Percobaan ulang maksimal ini selalu membuatku gila. Adakah yang keberatan jika saya menyelam dan melihat apakah saya tidak dapat menyusun PR untuk menekan pesan coba lagi?

Saya tidak bermaksud muncul entah dari mana, tetapi saya menggunakan banyak permintaan dalam pekerjaan Python yang kami lakukan di Cloudant. Kami mendapatkan halaman yang menyertakan hal percobaan ulang, dan itu bisa menjadi ikan haring merah.

Jawabannya adalah _mungkin_.

Masalahnya adalah, meskipun secara default kami tidak melakukan percobaan ulang apa pun, Anda dapat mengonfigurasi Permintaan untuk mencoba kembali permintaan yang gagal secara otomatis. Dalam situasi tersebut, MaxRetryError kami bungkus benar-benar masuk akal. Jika Anda dapat menemukan solusi yang membuat MaxRetryError pada tempatnya saat seharusnya, tetapi menghapusnya saat Anda dapat menjamin tidak ada upaya percobaan ulang yang dilakukan, kami akan mempertimbangkannya. =)

@Lukasa terima kasih, saya menyegarkan diri saya di backlog di sini. Jika saya mendapat kesempatan untuk menyelam, saya pasti akan menjangkau.

Bagi saya sepertinya tempat yang tepat untuk perubahan ada di urllib3? MaxRetryError masuk akal untuk meningkatkan dalam konteks percobaan ulang otomatis, tetapi dalam kasus percobaan ulang nol (mungkin pengalaman permintaan naif) dapat membingungkan.

Di urllib3 tampaknya kesalahan yang membingungkan dapat dipicu di sini melalui permintaan. Hampir menyenangkan hanya menaikkan MaxRetryError ketika retries==0 and max_retries!=0 . Jika max_retries==0 alih-alih menaikkan, RequestError biasa dimunculkan sebagai gantinya.

Saya melihat urllib3 seperti yang digunakan oleh permintaan ada dalam paket yang disertakan - hanya ingin tahu, mengapa demikian? Bagaimanapun, ini hanya beberapa ide yang ingin saya lemparkan ke sana. Saya masih mengejar basis kode.

Apakah perbaikan termasuk dalam urllib3 sepenuhnya tergantung pada @shazow. Mengingat bahwa urllib3 secara default _does_ coba lagi (3 kali IIRC), mungkin dia ingin mempertahankan perilaku urllib3 apa adanya. Ping dia untuk mendapatkan masukannya.

Kami vendor urllib3 untuk menghindari beberapa masalah ketergantungan. Pada dasarnya, ini berarti kami selalu beroperasi dengan versi urllib3 yang diketahui. Ini telah dibahas dengan panjang lebar di #1384 dan #1812 jika Anda menginginkan detail yang sulit.

Fiuh berpasir tapi informatif. @shazow ini hanya beberapa pemikiran yang saya miliki - meningkatkan RequestError daripada MaxRetryError seperti di atas. Sungguh saya pikir saya lebih memahami MaxRetryError setelah memeriksa urlopen .

Sunting ganda: Benar-benar hanya seorang kwarg sehingga seseorang dapat raise MaxRetryError(retries=0) dan mengubah pesan pada retries==0 .

Bagaimana dengan retries=False yang akan menonaktifkan percobaan ulang sama sekali dan selalu memunculkan pengecualian asli alih-alih MaxRetryError ?

Mampu membedakan antara meminta urlopen tanpa percobaan ulang dan menghitung mundur hingga 0 pada jumlah percobaan ulang akan berguna. Sangat mengejutkan melihat MaxRetryError ketika Anda tidak meminta percobaan ulang.

Jika ada yang ingin melakukan patch+test untuk ini, itu akan sangat dihargai. :)

@shazow hebat, saya akan bermain jika saya dapat menemukan siklusnya. Saya akan melakukan ping jika saya memiliki sesuatu.

\HAI/

^Saya ingin tahu apakah ada patch yang dirilis? Masalah ini tampaknya sudah berumur satu tahun.

Tidak sejauh yang saya ketahui. =)

retries=False harus menaikkan pengecualian asli pada v1.9, tanpa pembungkus.

@kevinburke pikiran?

Butuh sedikit waktu lagi

Kevin Burke
telepon: 925.271.7005 | dua puluhmilidetik.com

Pada hari Minggu, 5 Oktober 2014 pukul 10:37, Ian Cordasco [email protected]
menulis:

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


Balas email ini secara langsung atau lihat di GitHub
https://github.com/kennethreitz/requests/issues/1198#issuecomment -57945403
.

Ya ini sudah diperbaiki saya pikir

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

Bisakah Anda memberi tahu saya bagaimana ini telah diselesaikan, karena saya juga mendapatkan masalah koneksi yang ditolak di pihak saya. Dalam skrip python saya, saya mencoba menghubungkan server RPC

@SiddheshS Masalah ini telah diperbaiki dengan menulis ulang beberapa pengecualian: ini tidak ada hubungannya dengan kesalahan koneksi yang ditolak. Untuk meminta bantuan atas suatu masalah, Anda harus mempertimbangkan untuk menggunakan Stack Overflow .

Saya mengalami masalah yang sama. itu terjadi sesekali. bagaimana cara memperbaikinya, apakah ada yang bisa membantu saya? .Terima kasih.

request.exceptions.ConnectionError: HTTPSConnectionPool(host='api.xxxx.com', port=443): Percobaan ulang maksimum terlampaui dengan url: /v2/goods/?category=0&sort_type=2&page_size=3&page_num=13&t=0&count=110 (Disebabkan oleh NewConnectionError(': Gagal membuat koneksi baru: [Errno 110] Connection timed out',))
Traceback (panggilan terakhir terakhir):
File "test.py", baris 335, di
utama()
File "test.py", baris 290, di main
hasil = get_goods_info()
File "test.py", baris 67, di get_goods_info
hasil = request.get(url)
File "/usr/local/lib/python2.7/site-packages/requests/api.py", baris 69, di get
kembali permintaan('dapatkan', url, params=params, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/api.py", baris 50, dalam permintaan
respon = session.request(metode=metode, url=url, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", baris 468, dalam permintaan
resp = self.send(persiapan, *_send_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", baris 576, di kirim
r = adapter.send(permintaan, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", baris 423, di kirim
naikkan ConnectionError(e, request=request)

@nkjulia Upaya koneksi kehabisan waktu, yang menunjukkan bahwa server jarak jauh kelebihan beban atau batas waktu koneksi Anda terlalu rendah.

saya juga sesat ini....

@kevinburke bagaimana masalah Anda teratasi setelah mendapatkan kesalahan koneksi ditolak? Bisa tolong sarannya sobat. TIA

Abaikan postingan saya sobat. Saya memiliki beberapa versi python di mesin saya karena itu tidak dapat memilih yang benar dan membuat kesalahan. Memposting pemikiran ini mungkin bermanfaat bagi seseorang.

Saya mengalami masalah yang sama. itu terjadi sesekali. bagaimana cara memperbaikinya, apakah ada yang bisa membantu saya? .Terima kasih.

request.exceptions.ConnectionError: HTTPSConnectionPool(host='api.xxxx.com', port=443): Percobaan ulang maksimum terlampaui dengan url: /v2/goods/?category=0&sort_type=2&page_size=3&page_num=13&t=0&count=110 (Disebabkan oleh NewConnectionError(': Gagal membuat koneksi baru: [Errno 110] Connection timed out',))
Traceback (panggilan terakhir terakhir):
File "test.py", baris 335, di
utama()
File "test.py", baris 290, di main
hasil = get_goods_info()
File "test.py", baris 67, di get_goods_info
hasil = request.get(url)
File "/usr/local/lib/python2.7/site-packages/requests/api.py", baris 69, di get
kembali permintaan('dapatkan', url, params=params, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/api.py", baris 50, dalam permintaan
respon = session.request(metode=metode, url=url, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", baris 468, dalam permintaan
resp = self.send(persiapan, *_send_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", baris 576, di kirim
r = adapter.send(permintaan, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", baris 423, di kirim
naikkan ConnectionError(e, request=request)

Jika masalah ini telah diselesaikan, tolong beri saya beberapa saran.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

remram44 picture remram44  ·  4Komentar

cnicodeme picture cnicodeme  ·  3Komentar

Matt3o12 picture Matt3o12  ·  3Komentar

JimHokanson picture JimHokanson  ·  3Komentar

brainwane picture brainwane  ·  3Komentar