簡體   English   中英

如何在python中重復異常?

[英]How to repeat something upon exception in python?

在python中導致異常之后重復某些事情的最優雅方法是什么?

我有這樣的東西[偽代碼作為例子]:

try:
  do_some_database_stuff()
except DatabaseTimeoutException:
  reconnect_to_database()
  do_some_database_stuff() # just do it again

但想象一下,如果我沒有一個很好的功能,而是很多代碼。 重復的代碼不是很好。

所以我認為這稍微好一些:

while True:
  try:
    do_some_database_stuff()
    break
  except DatabaseTimeoutException:
    reconnect_to_database()

如果異常確實解決了問題,那就足夠了。 如果不是,我需要一個計數器來防止無限循環:

i = 0
while i < 5:
  try:
    do_some_database_stuff()
    break
  except DatabaseTimeoutException:
    reconnect_to_database()
    i += 1

但后來我真的不知道它是否有效,所以它也是:

while i <= 5:
  try:
    do_some_database_stuff()
    break
  except DatabaseTimeoutException:
    if i != 5:
     reconnect_to_database()
    else:
      raise DatabaseTimeoutException
    i += 1

你可以看到它開始變得非常混亂。

表達這種邏輯的最優雅方式是什么?

  • 嘗試一下
  • 如果失敗則應用修復
  • 嘗試n次,包括修復
  • 如果它繼續失敗給我一個錯誤,以防止無限循環

您可以使用“ for-else ”循環:

for ii in range(5):
    try:
        do_some_database_stuff()
        break
    except DatabaseTimeoutException:
        reconnect_to_database()
else:
    raise DatabaseTimeoutException

或者,沒有:

for ii in range(5):
    try:
        do_some_database_stuff()
        break
    except DatabaseTimeoutException:
        if ii == 4:
            raise
        reconnect_to_database()

我個人不是for-else構造的粉絲。 我不認為它是直觀的。 我第一次閱讀它時,我認為這意味着“為循環(...)做,如果迭代是空的那么......”。

您應該將代碼放在函數中。 如果do_some_database_stuff()成功完成,那么您可以使用return語句從函數中提前返回。

例如。

def try_to_do_some_database_stuff():
    for i in range(num_times):
        try:
            return do_some_database_stuff()
        except DatabaseTimeoutException:
            reconnect_to_database()
    raise DatabaseTimeoutException

如果你發現自己使用這個構造很多,那么你可以使它更通用。

def try_to_do(func, catch, times=2, on_exception=None):
    for i in range(times):
        try:
            return func()
        except catch:
            if on_exception:
                on_exception()
    raise catch

try_to_do(do_some_database_stuff, catch=DatabaseTimeoutException, times=5, 
    on_exception=reconnect_to_database)

如果需要將參數傳遞給函數,可以使用functools.partial

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM