例外の後に再試行するには?
-
21-09-2019 - |
質問
私はfor i in range(0, 100)
で始まるループを持っています。通常、それは正常に動作しますが、時にはそれがネットワークの状態に起因する障害が発生しました。現在、私はそれが失敗した場合に、それは句(continue
ための次の番号に進み)以外にi
するように設定されています。
i
に同じ番号を再割り当てして実行するために、それは可能ですか?
解決
あなたのforループ、置くあなたのwhile True
コードの内部の内側try
を行い、そしてあなたのコードが成功した場合にのみ、そのwhile
ループから壊れています。
for i in range(0,100):
while True:
try:
# do stuff
except SomeSpecificException:
continue
break
他のヒント
私はこのように、その特定の項目に問題がある場合は、最終的には、次のいずれかに続けるように、再試行の回数を制限することを好むます:
for i in range(100):
for attempt in range(10):
try:
# do thing
except:
# perhaps reconnect, etc.
else:
break
else:
# we failed all the attempts - deal with the consequences.
再試行にパッケージが失敗した場合に、コードのブロックを再試行するための良い方法です。
例えば、
@retry(wait_random_min=1000, wait_random_max=2000)
def wait_random_1_to_2_s():
print("Randomly wait 1 to 2 seconds between retries")
ここで他の人に同様のソリューションですが、それが所定の数やリトライで成功しない場合、それは例外が発生します。
tries = 3
for i in range(tries):
try:
do_the_thing()
except KeyError as e:
if i < tries - 1: # i is zero indexed
continue
else:
raise
break
以上のもの醜いのwhileループを使用せずに「機能的」アプローチ:
def tryAgain(retries=0):
if retries > 10: return
try:
# Do stuff
except:
retries+=1
tryAgain(retries)
tryAgain()
最も明確な方法は、明示的に設定i
になります。たとえばます:
i = 0
while i < 100:
i += 1
try:
# do stuff
except MyException:
continue
再帰を使用して
for i in range(100):
def do():
try:
## Network related scripts
except SpecificException as ex:
do()
do() ## invoke do() whenever required inside this loop
タイムアウトと一般的な解決策ます:
import time
def onerror_retry(exception, callback, timeout=2, timedelta=.1):
end_time = time.time() + timeout
while True:
try:
yield callback()
break
except exception:
if time.time() > end_time:
raise
elif timedelta > 0:
time.sleep(timedelta)
使用方法:
for retry in onerror_retry(SomeSpecificException, do_stuff):
retry()
Pythonのデコレータライブラリの中に似たものがあります。
それはない例外のテストが、戻り値を行いますことを心に留めておいてください。装飾された関数がTrueを返すまで、再試行します。
A、わずかに修正されたバージョンは、トリックを行う必要があります。
for _ in range(5):
try:
# replace this with something that may fail
raise ValueError("foo")
# replace Exception with a more specific exception
except Exception as e:
err = e
continue
# no exception, continue remainder of code
else:
break
# did not break the for loop, therefore all attempts
# raised an exception
else:
raise err
私のバージョンは、上記のいくつかに似ていますが、別のwhile
ループを使用し、すべての再試行が失敗した場合、最新の例外を再発生させていません。明示的にセットトップでerr = None
が、エラーがあったため、else
が設定されます。
err
ブロックを実行しなければならないよう、厳密には必要ありませんでした しばらくしてカウンターを使用します:
count = 1
while count <= 3: # try 3 times
try:
# do_the_logic()
break
except SomeSpecificException as e:
# If trying 3rd time and still error??
# Just throw the error- we don't have anything to hide :)
if count == 3:
raise
count += 1
あなたは、パッケージを再試行のPythonを使用することができます。 再試行する
ちょうど約何にも再試行動作を追加する作業を簡素化するためにはPythonで書かれています。
あなたはネストされたループのないソリューションをしたい場合は、あなたが開発者の任意のiterableのクイックラップbreak
を成功にretriable
を可能性があり呼び出します。保存された認証が期限切れになる - ここで私は、多くの場合に実行することをネットワークの問題の例を示します。それの使用は、次のように読みます。
client = get_client()
smart_loop = retriable(list_of_values):
for value in smart_loop:
try:
client.do_something_with(value)
except ClientAuthExpired:
client = get_client()
smart_loop.retry()
continue
except NetworkTimeout:
smart_loop.retry()
continue
私は私のコードでは以下を使用し、
for i in range(0, 10):
try:
#things I need to do
except ValueError:
print("Try #{} failed with ValueError: Sleeping for 2 secs before next try:".format(i))
time.sleep(2)
continue
break
私は最近、この問題への解決策に私のpythonで働いていたし、私はそれが必要な場合は、フィードバックを与えてくださいstackoverflowの訪問者とそれを共有することが幸せです。
print("\nmonthly salary per day and year converter".title())
print('==' * 25)
def income_counter(day, salary, month):
global result2, result, is_ready, result3
result = salary / month
result2 = result * day
result3 = salary * 12
is_ready = True
return result, result2, result3, is_ready
i = 0
for i in range(5):
try:
month = int(input("\ntotal days of the current month: "))
salary = int(input("total salary per month: "))
day = int(input("Total Days to calculate> "))
income_counter(day=day, salary=salary, month=month)
if is_ready:
print(f'Your Salary per one day is: {round(result)}')
print(f'your income in {day} days will be: {round(result2)}')
print(f'your total income in one year will be: {round(result3)}')
break
else:
continue
except ZeroDivisionError:
is_ready = False
i += 1
print("a month does'nt have 0 days, please try again")
print(f'total chances left: {5 - i}')
except ValueError:
is_ready = False
i += 1
print("Invalid value, please type a number")
print(f'total chances left: {5 - i}')
ここでは、この問題を解決する方法についての私の考えだ。
j = 19
def calc(y):
global j
try:
j = j + 8 - y
x = int(y/j) # this will eventually raise DIV/0 when j=0
print("i = ", str(y), " j = ", str(j), " x = ", str(x))
except:
j = j + 1 # when the exception happens, increment "j" and retry
calc(y)
for i in range(50):
calc(i)
あなたのループ変数をインクリメントtry節は、
成功した場合にのみ、