Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python retry using the tenacity module

I'm having having difficulty getting the tenacity library to work as expected. The retry in the following test doesn't trigger at all. I would expect a retry every 5 seconds and for the log file to reflect the retry attempts.

import paramiko
import tenacity
from configparser import RawConfigParser
import logging

def main():
    parser = RawConfigParser()
    parser.read('config.ini')
    HOST = parser['SSH']['host']
    PORT = parser['SSH']['port']
    USER = parser['SSH']['user']
    LOG_LEVEL = parser['Logging']['level']
    LOG_FILE = parser['Files']['log_file']
    LOG_FORMAT = parser['Logging']['format']

    with open(LOG_FILE, "a") as f:
        logging.basicConfig(filename=LOG_FILE,level=LOG_LEVEL,format=LOG_FORMAT)
        logging.info("******Started logging******")

    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    @tenacity.retry(wait=tenacity.wait_fixed(5))
    def connect():
        try:
            client.connect(HOST, int(PORT), USER)
            logging.info("Successful connection to remote server")
        except Exception:
            logging.error("Cannot connect to remote server")

    connect()

if __name__ == "__main__":
    main()

The log file spits this out:

> 2017-11-04 19:55:20,695 ******Started logging******
> 2017-11-04 19:55:20,695 Cannot connect to remote server
like image 627
Clive van Hilten Avatar asked Nov 04 '17 20:11

Clive van Hilten


People also ask

How does tenacity retry work?

Tenacity allows you to retry a code block without the need to wraps it in an isolated function. This makes it easy to isolate failing block while sharing context. The trick is to combine a for loop and a context manager. You can configure every details of retry policy by configuring the Retrying object.

How do I use retry in Python?

Examples. @retry(ZeroDivisionError, tries=3, delay=2) def make_trouble(): '''Retry on ZeroDivisionError, raise error after 3 attempts, sleep 2 seconds between attempts. ''' @retry((ValueError, TypeError), delay=1, backoff=2) def make_trouble(): '''Retry on ValueError or TypeError, sleep 1, 2, 4, 8, ...

What is tenacity in Python?

Tenacity is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of adding retry behavior to just about anything. It originates from a fork of retrying. The simplest use case is retrying a flaky function whenever an Exception occurs until a value is returned.


1 Answers

I suppose that tenacity detects failures by handling exceptions. In your code the exception is logged and then discarded. So, for tenacity, your call is actually successful. You should re-raise this exception to get the expected behavior. Like this:

@tenacity.retry(wait=tenacity.wait_fixed(5))
def connect():
    try:
        client.connect(HOST, int(PORT), USER)
        logging.info("Successful connection to remote server")
    except Exception:
        logging.error("Cannot connect to remote server")
        raise
like image 185
Piotr Babij Avatar answered Sep 22 '22 22:09

Piotr Babij