346

で始まるループがありますfor i in range(0, 100)。通常は正常に動作しますが、ネットワークの状態により失敗することがあります。現在、失敗continueした場合にexcept節になるように設定しています( の次の番号に進みiます)。

同じ番号を に再割り当てしiて、失敗したループの反復をもう一度実行することはできますか?

4

25 に答える 25

476

while Truefor ループ内で実行し、tryコードを内部に配置whileし、コードが成功した場合にのみそのループから抜け出します。

for i in range(0,100):
    while True:
        try:
            # do stuff
        except SomeSpecificException:
            continue
        break
于 2010-01-18T05:02:20.820 に答える
282

再試行の回数を制限することを好みます。そのため、その特定のアイテムに問題がある場合、最終的に次のアイテムに進むことができます。

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.
于 2011-10-05T15:03:37.973 に答える
19

retrying:tenacityおよびbackoff(2020 年更新)の代替

ライブラリの再試行は以前の方法でしたが、残念ながらいくつかのバグがあり、2016 年以降更新されていませ。これを書いている間、テナシティにはより多くの GItHub スター (2.3k 対 1.2k) があり、最近更新されたので、それを使用することにしました。次に例を示します。

from functools import partial
import random # producing random errors for this example

from tenacity import retry, stop_after_delay, wait_fixed, retry_if_exception_type

# Custom error type for this example
class CommunicationError(Exception):
    pass

# Define shorthand decorator for the used settings.
retry_on_communication_error = partial(
    retry,
    stop=stop_after_delay(10),  # max. 10 seconds wait.
    wait=wait_fixed(0.4),  # wait 400ms 
    retry=retry_if_exception_type(CommunicationError),
)()


@retry_on_communication_error
def do_something_unreliable(i):
    if random.randint(1, 5) == 3:
        print('Run#', i, 'Error occured. Retrying.')
        raise CommunicationError()

for i in range(100):
    do_something_unreliable(i)

上記のコードは次のようなものを出力します。

Run# 3 Error occured. Retrying.
Run# 5 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 10 Error occured. Retrying.
.
.
.

のその他の設定は、 tenacity GitHub ページtenacity.retryにリストされています。

于 2020-06-01T12:40:20.993 に答える
15

これらのい while ループを使用しない、より「機能的な」アプローチ:

def tryAgain(retries=0):
    if retries > 10: return
    try:
        # Do stuff
    except:
        retries+=1
        tryAgain(retries)

tryAgain()
于 2010-10-28T20:46:42.283 に答える
11

最も明確な方法は、明示的に設定することiです。例えば:

i = 0
while i < 100:
    i += 1
    try:
        # do stuff

    except MyException:
        continue
于 2010-01-18T05:13:47.440 に答える
9
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を実行する必要があるため、厳密には必要ありません。elseerr

于 2019-02-05T15:50:25.207 に答える
4

再帰の使用

for i in range(100):
    def do():
        try:
            ## Network related scripts
        except SpecificException as ex:
            do()
    do() ## invoke do() whenever required inside this loop
于 2016-08-31T12:06:23.130 に答える
4

while とカウンターの使用:

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
于 2016-08-31T11:57:34.353 に答える
4

Python Decorator Libraryにも似たようなものがあります。

例外をテストするのではなく、戻り値をテストすることに注意してください。装飾された関数が True を返すまで再試行します。

わずかに変更されたバージョンでうまくいくはずです。

于 2011-06-15T07:58:16.273 に答える
-10

try 句が成功した場合にのみ、ループ変数をインクリメントします

于 2010-01-18T09:34:27.510 に答える