@backoff
関連情報がないのでここにメモします。
pythonでbackoffは特定なエラーが発生するとそれをバックオップさせ、リトライをするデコレーターです。
まずpipインストールをします。
$ pip install backoff
Collecting backoff
Downloading backoff-1.11.1-py2.py3-none-any.whl (13 kB)
Installing collected packages: backoff
Successfully installed backoff-1.11.1
簡単な例えを見ましょう。
def test():
number = int(input("Enter an integer: "))
test()
このコードを実行しintではない値を与えたらValueErrorが発生しますが、入力の誤りを三回くらいは勘弁しようと思います。方法は二つです。
-
input(...)
の結果をタイプをチェックしてintであればPass, そうじゃなければindicator変数を指定してこの変数が3を超えたらVauleErrorを発生させる。 -
@backoff
を使用する。
一番目はコードの修正範囲が広いので複雑になります。だから二番目を使用します。
import backoff
@backoff.on_exception(backoff.expo,
ValueError,
max_tries=3)
def test():
number = int(input("Enter an integer: "))
test()
実行結果です。
$ python3 3test.py
Enter an integer: e
Enter an integer: r
Enter an integer: t
Traceback (most recent call last):
File "3test.py", line 9, in <module>
test()
File "/home/ubuntu/.local/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
ret = target(*args, **kwargs)
File "3test.py", line 7, in test
number = int(input("Enter an integer: "))
ValueError: invalid literal for int() with base 10: 't'
@backoff
デコレーターでmax_tries=3
を設定するとリトライを三回してもう一度誤りの値が与えられたらVauleError
を発生させます。
これが有用な場合はAPIサーバーとかDBのような異なるサーバーで接続する時です。次のコードはDB接続+HTTP request接続をするコードの一部の抜粋です(from the book “Robust Python”)。
import backoff
import requests
from autokitchen.database import OperationException
# setting properties of self.*_db objects will
# update data in the database
@backoff.on_exception(backoff.expo,
OperationException,
max_tries=5)
def on_dish_ordered(dish: Dish):
self.dish_db[dish].count += 1
@backoff.on_exception(backoff.expo,
OperationException,
max_tries=5)
@backoff.on_exception(backoff.expo,
requests.exceptions.HTTPError,
max_time=60)
def save_inventory_counts(inventory):
for ingredient in inventory:
self.inventory_db[ingredient.name] = ingredient.count
一番目の関数on_dish_ordered
の@backoff
はDBの接続がOperationException
で失敗すれば最大5回までリトライさせます。
二番目の関数save_inventory_counts
は@backoff
を重ねて使用してます。save_inventory_counts
がDBとHTTP.request両方を使っているので一番目の@backoff
はDBのOperationException
発生際5回まで、二番目の@backoff
ではHTTPError
発生際60秒(max_time=60
)までリトライさせます。