আমি কি অনুরোধের জন্য সর্বোচ্চ_ট্রি সেট করতে পারি?


181

পাইথন অনুরোধগুলির মডিউলটি সহজ এবং মার্জিত তবে একটি জিনিস আমাকে বাগিয়ে দেয় gs এটা একটা পাওয়ার সম্ভাবনা আছে requests.exception.ConnectionError মত একটি বার্তা:

Max retries exceeded with url: ...

এটি সূচিত করে যে অনুরোধগুলি ডেটা অ্যাক্সেস করার চেষ্টা করতে পারে বেশ কয়েকবার। তবে ডক্সের কোথাও এই সম্ভাবনার একক উল্লেখ নেই। উত্স কোডটি দেখে আমি এমন কোনও জায়গা পাইনি যেখানে আমি ডিফল্ট (সম্ভবত 0) মানটি পরিবর্তন করতে পারি।

তাহলে কি কোনওভাবেই অনুরোধের জন্য সর্বোচ্চ সংখ্যক পুনরায় চেষ্টা করা সম্ভব?


9
2.x এ অনুরোধের সাথে এ সম্পর্কে কোনও আপডেট আছে? একটি অনুরোধগুলি পছন্দ করবে (
প্যারাগব্যাক্সি

11
@paragbaxi: এবং আরও ভাল একটিrequests.get(url, max_retries=num_max_retries, dely_between_retries=3))
ওউজে

1
@ ওজেজে আমি আপনার উদাহরণগুলি গ্রহণ করেছি এবং এটি বাস্তব করে তুলেছি ;) just.getএবং গিথুবjust.post . com
kootenpv/

2
অনুরোধগুলির সাথে পুনরায় চেষ্টা সম্পর্কে দরকারী নিবন্ধ: পিটারবে.com
গোকুল

উত্তর:


161

এটি অন্তর্নিহিত urllib3লাইব্রেরি যা আবার চেষ্টা করছে। একটি পৃথক সর্বোচ্চ পুনরায় চেষ্টা গণনা সেট করতে বিকল্প পরিবহন অ্যাডাপ্টার ব্যবহার করুন :

from requests.adapters import HTTPAdapter

s = requests.Session()
s.mount('http://stackoverflow.com', HTTPAdapter(max_retries=5))

max_retriesযুক্তি একটি পূর্ণসংখ্যা বা লাগে Retry()বস্তুর ; পরবর্তীটি আপনাকে কী ধরণের ব্যর্থতা পুনরায় চেষ্টা করা হয় তার উপর সূক্ষ্ম-নিয়ন্ত্রণযুক্ত নিয়ন্ত্রণ দেয় (একটি পূর্ণসংখ্যার মানটি একটি Retry()উদাহরণে রূপান্তরিত হয় যা কেবল সংযোগ ব্যর্থতাগুলি পরিচালনা করে; সংযোগ করার পরে ত্রুটিগুলি ডিফল্টরূপে পরিচালিত হয় না কারণ এগুলি পার্শ্ব-প্রতিক্রিয়া হতে পারে) ।


পুরানো উত্তর, অনুরোধ প্রকাশের পূর্বে 1.2.1 :

requestsগ্রন্থাগার সত্যিই এই কনফিগারযোগ্য দেখা যায় না, না এটা (দেখুন মনস্থ করে এই টান অনুরোধ )। বর্তমানে (অনুরোধ 1.1), পুনরায় চেষ্টা গণনা 0 তে সেট করা আছে আপনি যদি সত্যিই এটি কোনও উচ্চতর মান হিসাবে সেট করতে চান তবে আপনাকে বিশ্বব্যাপী এটি সেট করতে হবে:

import requests

requests.adapters.DEFAULT_RETRIES = 5

এই ধ্রুবকটি নথিভুক্ত নয়; এটি আপনার নিজের বিপদে ব্যবহার করুন কারণ ভবিষ্যতের প্রকাশগুলি কীভাবে এটি পরিচালনা করা যায় তা পরিবর্তন করতে পারে।

আপডেট : এবং এই করেনি পরিবর্তন; সংস্করণ 1.2.1 মধ্যে সেট করতে বিকল্প max_retriesপরামিতি উপর HTTPAdapter()বর্গ , যোগ করা হয়েছিল যাতে এখন আপনি বিকল্প পরিবহন অ্যাডাপ্টার ব্যবহার করতে হবে, উপরোক্ত দেখুন। আপনি যদি ডিফল্টদেরও প্যাচ না করেন তবে বানর-প্যাচ পদ্ধতির কাজ আর হবে না HTTPAdapter.__init__()very


9
এটি প্রয়োজন না হলে প্রতিটি সাইটের জন্য আপনাকে এটি নির্দিষ্ট করতে হবে না। আপনি কেবল এটি করতে পারেন এটি session.mount('http://', HTTPAdapter(max_retries=10))সমস্ত HTTP সংযোগের জন্য কাজ করবে। Https এর সাথে একই তখন সমস্ত https সংযোগের জন্য কাজ করবে।
ব্যবহারকারী 136036

1
@ ব্যবহারকারী 136036: হ্যাঁ, অ্যাডাপ্টারগুলি দীর্ঘতম উপসর্গ ম্যাচ দ্বারা সন্ধান করা হয়; আপনি যদি সমস্ত ইউআরএলগুলিতে এটি প্রয়োগ করতে চান http://এবং https://ব্যবহার করার জন্য সর্বনিম্ন উপসর্গ হন তবে ডকুমেন্টেশনটির উত্তর লিঙ্কগুলি দেখুন।
মার্টিজন পিটারস

1
দ্রষ্টব্য যে HTTPAdapter(max_retries=5)কেবলমাত্র নির্দিষ্ট দৃশ্যের জন্য কাজ করবে। অনুরোধ ডক থেকে , Note, this applies only to failed DNS lookups, socket connections and connection timeouts, never to requests where data has made it to the server. By default, Requests does not retry failed connections.কোনও স্থিতি কোডের জন্য পুনরায় চেষ্টা করতে, নীচে @ ডাটাশামানের উত্তর দেখুন।
স্টিভেন জু

@ স্টিভেন এক্সু: হ্যাঁ, Retry()ব্যর্থতার পরিস্থিতিতে কী চেষ্টা করা হয়েছে তা পরিবর্তন করতে আপনি কনফিগার করতে পারেন।
মার্টিজন পিটারস

224

এটি কেবল সর্বোচ্চ_আপনিগুলিকেই পরিবর্তন করবে না এমন একটি ব্যাকঅফ কৌশলও সক্ষম করবে যা সমস্ত http: // ঠিকানার জন্য অনুরোধ করে পুনরায় চেষ্টা করার আগে (মোট 5 বার):

import requests
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter

s = requests.Session()

retries = Retry(total=5,
                backoff_factor=0.1,
                status_forcelist=[ 500, 502, 503, 504 ])

s.mount('http://', HTTPAdapter(max_retries=retries))

s.get('http://httpstat.us/500')

এর জন্য ডকুমেন্টেশন অনুসারেRetry : যদি ব্যাক অফ_ফ্যাক্টরটি 0.1 হয় , তবে ঘুম () আবার চেষ্টা করার মধ্যে [0.1 সে, 0.2 সে, 0.4 সে, ...] এর জন্য ঘুমাবে। স্থিতি কোডটি 500 , 502 , 503 বা 504 হয় তবে এটি পুনরায় চেষ্টা করতে বাধ্য করবে ।

Retryআরও দানাদার নিয়ন্ত্রণের জন্য বিভিন্ন অন্যান্য বিকল্প :

  • মোট - অনুমোদনের জন্য পুনরায় প্রচেষ্টার সংখ্যা।
  • সংযুক্ত - পুনরায় চেষ্টা করার জন্য সংযোগ-সংক্রান্ত কত ত্রুটি।
  • পড়ুন - কতবার পড়ার ত্রুটিগুলিতে পুনরায় চেষ্টা করতে হবে।
  • পুনর্নির্দেশ - কতগুলি পুনঃনির্দেশ সম্পাদন করতে হবে।
  • মেথড_হাইটালিস্ট - বড় আকারের এইচটিটিপি পদ্ধতি ক্রিয়াগুলির সেট করুন যা আমাদের আবার চেষ্টা করা উচিত।
  • status_forcelist - এইচটিটিপি স্থিতি কোডগুলির একটি সেট যা আমাদের আবার চেষ্টা করার চেষ্টা করা উচিত।
  • ব্যাকঅফ_ফ্যাক্টর - প্রচেষ্টাগুলির মধ্যে প্রয়োগ করার জন্য একটি ব্যাকঅফ ফ্যাক্টর।
  • উত্সাহ_আন_প্রত্যক্ষ - পুনর্নির্দেশের সংখ্যাটি শেষ হয়ে গেলেও , একটি উত্থাপন করতে MaxRetryError, বা 3xx পরিসরে রেসপন্স কোড সহ প্রতিক্রিয়া ফিরিয়ে আনতে হবে কিনা ।
  • raise_on_status - অনুরূপ অর্থ raise_on_redirect : কিনা আমরা একটি ব্যতিক্রম বাড়াতে হবে, অথবা একটি প্রতিক্রিয়া পাঠাচ্ছে, স্থিতি পড়ে যদি status_forcelist পরিসীমা এবং চেষ্টার ক্লান্ত করা হয়েছে।

বিশেষ দ্রষ্টব্য : raise_on_status অপেক্ষাকৃত নতুন, এবং এখনো urllib3 বা অনুরোধের মুক্তি সেটিকে করেছে। Raise_on_status শব্দ যুক্তি পাইথন সংস্করণ 3.6 মধ্যে সর্বাধিক মান গ্রন্থাগার সেটিকে করেছেন বলে মনে হচ্ছে।

নির্দিষ্ট এইচটিটিপি স্থিতি কোডগুলিতে পুনরায় চেষ্টা করার জন্য, স্থিতি_পরেসিলিস্ট ব্যবহার করুন । উদাহরণস্বরূপ, status_forcelist = [503] স্থিতি কোড 503 এ পুনরায় চেষ্টা করবে (পরিষেবাটি উপলভ্য নয়)।

ডিফল্টরূপে, পুনরায় চেষ্টা করুন কেবলমাত্র এই শর্তগুলির জন্য:

  • পুল থেকে সংযোগ পেতে পারেনি।
  • TimeoutError
  • HTTPExceptionউত্থাপিত ( http.client থেকে ) পাইথন 3-তে অন্য httplib )। এটি URL- এ বা প্রোটোকলের মতো সঠিকভাবে গঠিত না হওয়ায় এটি নিম্ন-স্তরের HTTP ব্যতিক্রম বলে মনে হচ্ছে।
  • SocketError
  • ProtocolError

লক্ষ্য করুন যে এগুলি সমস্ত ব্যতিক্রম যা নিয়মিত এইচটিটিপি প্রতিক্রিয়া প্রাপ্ত হতে বাধা দেয়। যদি কোনও নিয়মিত প্রতিক্রিয়া উত্পন্ন হয়, তবে পুনরায় চেষ্টা করা হবে না। স্ট্যাটাস_ফোর্সালিস্ট ব্যবহার না করে , স্ট্যাটাস 500 এর সাথে একটি প্রতিক্রিয়াও আবার চেষ্টা করা হবে না।

এটিকে এমনভাবে আচরণ করতে যাতে কোনও রিমোট API বা ওয়েব সার্ভারের সাথে কাজ করার জন্য আরও স্বজ্ঞাত, আমি উপরের কোড স্নিপেট ব্যবহার করব, যা স্ট্যাটাস 500 , 502 , 503 এবং 504 এ পুনরায় চেষ্টা করে , যার সবগুলিই অসাধারণ নয় ওয়েব এবং (সম্ভবত) পুনরুদ্ধারযোগ্যকে যথেষ্ট বড় ব্যাক অফ সময় দেওয়া হয়েছে।

সম্পাদিত : urllib3Retry থেকে সরাসরি ক্লাস আমদানি করুন ।


1
আমি আপনার যুক্তিটি বাস্তবায়নের চেষ্টা করছি, তবে আমি জানি না এটি কাজ করছে কিনা কারণ লগটি কেবল একটি অনুরোধ দেখায় এমনকি রেস স্ট্যাটাস 503 রয়েছে। পুনরায় চেষ্টা করা হচ্ছে কিনা আমি কীভাবে জানতে পারি? কোডটি দেখুন: পেস্টবিন.com/rty4bKTw
ড্যানিলো অলিভিরা

1
সংযুক্ত কোডটি প্রত্যাশার মতো কাজ করে। কৌতুকটি হ'ল স্ট্যাটাস_ফরোলিস্ট প্যারামিটার। এটি urllib3 প্যাকেজটিকে নির্দিষ্ট স্থিতি কোডগুলি পুনরায় চেষ্টা করতে বলে। কোড: পেস্টবিন.
com

1
urllib3 মনে করে না (এবং হওয়া উচিত নয়) যে অবস্থা 503 একটি ব্যতিক্রম (ডিফল্টরূপে)।
দতাশামান

1
@ কননার, অ্যাডাপ্টারটি সেশনের সাথে সংযুক্ত রয়েছে।
দতাশমন

1
urlib3.Retry আর অনুরোধের অংশ নয়। এটি সরাসরি আমদানি করতে হবে। প্রস্তাবিত সম্পাদনা
ব্যবহারকারী 2390183

59

সতর্কতা অবলম্বন করুন, মার্টিজন পিটারসের উত্তরটি 1.2.1+ সংস্করণে উপযুক্ত নয়। আপনি লাইব্রেরিকে প্যাচ না করে বিশ্বব্যাপী সেট করতে পারবেন না।

পরিবর্তে আপনি এটি করতে পারেন:

import requests
from requests.adapters import HTTPAdapter

s = requests.Session()
s.mount('http://www.github.com', HTTPAdapter(max_retries=5))
s.mount('https://www.github.com', HTTPAdapter(max_retries=5))

22
দুর্দান্ত সমাধান তবে লক্ষ্য করুন যে পুনরায় চেষ্টা করার মধ্যে কোনও বিলম্ব নেই। আপনি যদি চেষ্টাগুলির মধ্যে ঘুমাতে চান, আপনার নিজের রোল করতে হবে।
নোফিনেটর

18

এখানে কয়েকটি উত্তরের সাথে কিছুটা লড়াই করার পরে, আমি ব্যাক অফ নামে একটি লাইব্রেরি পেয়েছি যা আমার পরিস্থিতির জন্য আরও ভাল কাজ করেছে। একটি প্রাথমিক উদাহরণ:

import backoff

@backoff.on_exception(
    backoff.expo,
    requests.exceptions.RequestException,
    max_tries=5,
    giveup=lambda e: e.response is not None and e.response.status_code < 500
)
def publish(self, data):
    r = requests.post(url, timeout=10, json=data)
    r.raise_for_status()

আমি এখনও লাইব্রেরির স্থানীয় কার্যকারিতা শট দেওয়ার পরামর্শ দিচ্ছি, তবে যদি আপনার কোনও সমস্যা হয় বা আপনার আরও বিস্তৃত নিয়ন্ত্রণের প্রয়োজন হয় তবে ব্যাকঅফ একটি বিকল্প।


1
মহান গ্রন্থাগার, আপনাকে ধন্যবাদ! আমার চেয়ে অন্য যে কোনও কিছুর জন্য আমার এই কার্যকারিতাটির প্রয়োজন ছিল requests, সুতরাং এটি পুরোপুরি কার্যকর হয়!
ডেনিস গোলোমাজভ

3

উচ্চতর নিয়ন্ত্রণ অর্জনের একটি পরিষ্কার উপায় হ'ল পুনরায় চেষ্টা স্টাফটিকে কোনও ফাংশনে প্যাকেজ করা এবং ডেকোরেটর ব্যবহার করে সেই ফাংশনটিকে পুনরুদ্ধারযোগ্য করা এবং ব্যতিক্রমগুলি হোয়াইটলিস্ট করা।

আমি এখানে এটি তৈরি করেছি: http://www.praddy.in/retry-decorator- whitelisted-exception/

সেই লিঙ্কটিতে কোডটি পুনরুত্পাদন করা হচ্ছে:

def retry(exceptions, delay=0, times=2):
"""
A decorator for retrying a function call with a specified delay in case of a set of exceptions

Parameter List
-------------
:param exceptions:  A tuple of all exceptions that need to be caught for retry
                                    e.g. retry(exception_list = (Timeout, Readtimeout))
:param delay: Amount of delay (seconds) needed between successive retries.
:param times: no of times the function should be retried


"""
def outer_wrapper(function):
    @functools.wraps(function)
    def inner_wrapper(*args, **kwargs):
        final_excep = None  
        for counter in xrange(times):
            if counter > 0:
                time.sleep(delay)
            final_excep = None
            try:
                value = function(*args, **kwargs)
                return value
            except (exceptions) as e:
                final_excep = e
                pass #or log it

        if final_excep is not None:
            raise final_excep
    return inner_wrapper

return outer_wrapper

@retry(exceptions=(TimeoutError, ConnectTimeoutError), delay=0, times=3)
def call_api():
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.