How to implement retry mechanism into python requests library?

前端 未结 6 2025
春和景丽
春和景丽 2020-12-02 10:12

I would like to add a retry mechanism to python request library, so scripts that are using it will retry for non fatal errors.

At this moment I do consider three kin

6条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-02 10:37

    I was able to obtain the desired level of reliability by extending requests.Session class.

    Here is the code https://bitbucket.org/bspeakmon/jira-python/src/a7fca855394402f58507ca4056de87ccdbd6a213/jira/resilientsession.py?at=master

    EDIT That code was:

    from requests import Session
    from requests.exceptions import ConnectionError
    import logging
    import time
    
    
    class ResilientSession(Session):
    
        """
        This class is supposed to retry requests that do return temporary errors.
    
        At this moment it supports: 502, 503, 504
        """
    
        def __recoverable(self, error, url, request, counter=1):
            if hasattr(error,'status_code'):
                if error.status_code in [502, 503, 504]:
                    error = "HTTP %s" % error.status_code
                else:
                    return False
            DELAY = 10 * counter
            logging.warn("Got recoverable error [%s] from %s %s, retry #%s in %ss" % (error, request, url, counter, DELAY))
            time.sleep(DELAY)
            return True
    
    
        def get(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).get(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
                if self.__recoverable(r, url, 'GET', counter):
                    continue
                return r
    
        def post(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).post(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
                if self.__recoverable(r, url, 'POST', counter):
                    continue
                return r
    
        def delete(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).delete(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
                if self.__recoverable(r, url, 'DELETE', counter):
                    continue
                return r
    
        def put(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).put(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
    
                if self.__recoverable(r, url, 'PUT', counter):
                    continue
                return r
    
        def head(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).head(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
                if self.__recoverable(r, url, 'HEAD', counter):
                    continue
                return r
    
        def patch(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).patch(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
    
                if self.__recoverable(r, url, 'PATCH', counter):
                    continue
                return r
    
        def options(self, url, **kwargs):
            counter = 0
            while True:
                counter += 1
                try:
                    r = super(ResilientSession, self).options(url, **kwargs)
                except ConnectionError as e:
                    r = e.message
    
                if self.__recoverable(r, url, 'OPTIONS', counter):
                    continue
                return r
    

提交回复
热议问题