Ну-ка, еще разок

Питоний пакет retrying - универсальная заплатка для кода, который может поломаться из-за внешних причин. Например, socket.connect() может закончится ошибкой из-за непредвиденной ситуации в сети. Заворачиваем вызов в @retry и бац! Все работает.

@retry
def create_connection(address):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    return socket.connect(address)

Однако бездумное применение @retry, как нетрудно догадаться, приводит проблемам. Самый известный пример - вложенные @retry. @retry(stop_max_attempt_number=3) вложенный в другой @retry(stop_max_attempt_number=3) дает 9 повторов. Три уровня вложенности - 27 повторов.

Один раз использование @retry привело к тому, что IT заблокировало мою учетную запись. Банальная история - был некий скрипт, который при запуске спрашивал логин и пароль для авторизации. В один прекрасный день некто (не будем показывать пальцем, хотя это был Слонёнок) усовершенствовал скрип, завернув сетевой вызов в @retry. Отличная идея, за исключением того, что ошибка авторизации приводила к повторному запросу с тем же неправильным именем и паролем. После определенного числа попыток контроллер домена решил, что кто-то пытается подобрать пароль к учетной записи и заблокировал её.

Мораль истории - знайте свои ошибки в лицо и используйте параметр retry_on_exception.

comments powered by Disqus