标签归档:try-except

异常后如何重试?

问题:异常后如何重试?

我有一个以开头的循环for i in range(0, 100)。正常情况下,它可以正常运行,但有时由于网络条件而失败。目前,我已对其进行了设置,以便在失败时,它将continue在except子句中(继续到的下一个数字i)。

我是否可以将相同的数字重新分配给i循环并再次执行失败的循环?

I have a loop starting with for i in range(0, 100). Normally it runs correctly, but sometimes it fails due to network conditions. Currently I have it set so that on failure, it will continue in the except clause (continue on to the next number for i).

Is it possible for me to reassign the same number to i and run through the failed iteration of the loop again?


回答 0

做一个while True内部的for循环,把你的try代码中,并突破从while只有当你的代码的成功循环。

for i in range(0,100):
    while True:
        try:
            # do stuff
        except SomeSpecificException:
            continue
        break

Do a while True inside your for loop, put your try code inside, and break from that while loop only when your code succeeds.

for i in range(0,100):
    while True:
        try:
            # do stuff
        except SomeSpecificException:
            continue
        break

回答 1

我更喜欢限制重试的次数,这样,如果该特定项目有问题,您最终将继续进行下一个,因此:

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.

I prefer to limit the number of retries, so that if there’s a problem with that specific item you will eventually continue onto the next one, thus:

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.

回答 2

重试包是重试的代码块失败的好办法。

例如:

@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")

The retrying package is a nice way to retry a block of code on failure.

For example:

@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")

回答 3

这是一个与其他解决方案类似的解决方案,但是如果未按规定的次数或重试次数失败,则会引发异常。

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

Here is a solution similar to others, but it will raise the exception if it doesn’t succeed in the prescribed number or 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

回答 4

没有使用那些难看的while循环的更“实用”的方法:

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

tryAgain()

The more “functional” approach without using those ugly while loops:

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

tryAgain()

回答 5

最清晰的方法是显式设置i。例如:

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

    except MyException:
        continue

The clearest way would be to explicitly set i. For example:

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

    except MyException:
        continue

回答 6

带有超时的通用解决方案:

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()

A generic solution with a timeout:

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)

Usage:

for retry in onerror_retry(SomeSpecificException, do_stuff):
    retry()

回答 7

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被设置时才执行最后一个块。

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

My version is similar to several of the above, but doesn’t use a separate while loop, and re-raises the latest exception if all retries fail. Could explicitly set err = None at the top, but not strictly necessary as it should only execute the final else block if there was an error and therefore err is set.


回答 8

Python Decorator库中有类似的东西

请记住,它不会测试异常,而是返回值。重试,直到修饰的函数返回True。

稍加修改的版本应该可以解决问题。

There is something similar in the Python Decorator Library.

Please bear in mind that it does not test for exceptions, but the return value. It retries until the decorated function returns True.

A slightly modified version should do the trick.


回答 9

使用递归

for i in range(100):
    def do():
        try:
            ## Network related scripts
        except SpecificException as ex:
            do()
    do() ## invoke do() whenever required inside this loop

Using recursion

for i in range(100):
    def do():
        try:
            ## Network related scripts
        except SpecificException as ex:
            do()
    do() ## invoke do() whenever required inside this loop

回答 10

使用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

Using while and a counter:

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

回答 11

您可以使用Python重试包。 重试

它是用Python编写的,以简化将重试行为添加到几乎所有内容的任务。

You can use Python retrying package. Retrying

It is written in Python to simplify the task of adding retry behavior to just about anything.


回答 12

retryingtenacitybackoff(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()

上面的代码输出类似:

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.retry韧度GitHub页面上列出了的更多设置。

Alternatives to retrying: tenacity and backoff (2020 update)

The retrying library was previously the way to go, but sadly it has some bugs and it hasn’t got any updates since 2016. Other alternatives seem to be backoff and tenacity. During the time of writing this, the tenacity had more GItHub stars (2.3k vs 1.2k) and was updated more recently, hence I chose to use it. Here is an example:

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)

The above code outputs something like:

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.
.
.
.

More settings for the tenacity.retry are listed on the tenacity GitHub page.


回答 13

如果您想要一个没有嵌套循环且无需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

If you want a solution without nested loops and invoking break on success you could developer a quick wrap retriable for any iterable. Here’s an example of a networking issue that I run into often – saved authentication expires. The use of it would read like this:

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

回答 14

我在代码中使用以下代码,

   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

I use following in my codes,

   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

回答 15

attempts = 3
while attempts:
  try:
     ...
     ...
     <status ok>
     break
  except:
    attempts -=1
else: # executed only break was not  raised
   <status failed>

attempts = 3
while attempts:
  try:
     ...
     ...
     <status ok>
     break
  except:
    attempts -=1
else: # executed only break was not  raised
   <status failed>

回答 16

这是我对这个问题的看法。以下retry功能支持以下功能:

  • 成功时返回被调用函数的值
  • 如果尝试已用尽,则引发被调用函数的异常
  • 尝试次数的限制(0表示无限制)
  • 尝试之间等待(线性或指数)
  • 仅当异常是特定异常类型的实例时才重试。
  • 可选的尝试记录
import time

def retry(func, ex_type=Exception, limit=0, wait_ms=100, wait_increase_ratio=2, logger=None):
    attempt = 1
    while True:
        try:
            return func()
        except Exception as ex:
            if not isinstance(ex, ex_type):
                raise ex
            if 0 < limit <= attempt:
                if logger:
                    logger.warning("no more attempts")
                raise ex

            if logger:
                logger.error("failed execution attempt #%d", attempt, exc_info=ex)

            attempt += 1
            if logger:
                logger.info("waiting %d ms before attempt #%d", wait_ms, attempt)
            time.sleep(wait_ms / 1000)
            wait_ms *= wait_increase_ratio

用法:

def fail_randomly():
    y = random.randint(0, 10)
    if y < 10:
        y = 0
    return x / y


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler(stream=sys.stdout))

logger.info("starting")
result = retry.retry(fail_randomly, ex_type=ZeroDivisionError, limit=20, logger=logger)
logger.info("result is: %s", result)

有关更多信息,请参见我的帖子

Here is my take on this issue. The following retry function supports the following features:

  • Returns the value of the invoked function when it succeeds
  • Raises the exception of the invoked function if attempts exhausted
  • Limit for the number of attempts (0 for unlimited)
  • Wait (linear or exponential) between attempts
  • Retry only if the exception is an instance of a specific exception type.
  • Optional logging of attempts
import time

def retry(func, ex_type=Exception, limit=0, wait_ms=100, wait_increase_ratio=2, logger=None):
    attempt = 1
    while True:
        try:
            return func()
        except Exception as ex:
            if not isinstance(ex, ex_type):
                raise ex
            if 0 < limit <= attempt:
                if logger:
                    logger.warning("no more attempts")
                raise ex

            if logger:
                logger.error("failed execution attempt #%d", attempt, exc_info=ex)

            attempt += 1
            if logger:
                logger.info("waiting %d ms before attempt #%d", wait_ms, attempt)
            time.sleep(wait_ms / 1000)
            wait_ms *= wait_increase_ratio

Usage:

def fail_randomly():
    y = random.randint(0, 10)
    if y < 10:
        y = 0
    return x / y


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler(stream=sys.stdout))

logger.info("starting")
result = retry.retry(fail_randomly, ex_type=ZeroDivisionError, limit=20, logger=logger)
logger.info("result is: %s", result)

See my post for more info.


回答 17

这是我的解决方法:

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)

Here’s my idea on how to fix this:

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)

回答 18

我最近与我的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}')

i recently worked with my python on a solution to this problem and i am happy to share it with stackoverflow visitors please give feedback if it is needed.

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}')

回答 19

仅在try子句成功时增加循环变量

increment your loop variable only when the try clause succeeds


如何正确忽略异常

问题:如何正确忽略异常

当您只想执行try-except但不处理异常时,如何在Python中进行呢?

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass

When you just want to do a try-except without handling the exception, how do you do it in Python?

Is the following the right way to do it?

try:
    shutil.rmtree(path)
except:
    pass

回答 0

try:
    doSomething()
except: 
    pass

要么

try:
    doSomething()
except Exception: 
    pass

所不同的是,第一个也将赶上KeyboardInterruptSystemExit和类似的东西,这是直接来源于exceptions.BaseException,没有exceptions.Exception

有关详细信息,请参见文档:

try:
    doSomething()
except: 
    pass

or

try:
    doSomething()
except Exception: 
    pass

The difference is that the first one will also catch KeyboardInterrupt, SystemExit and stuff like that, which are derived directly from exceptions.BaseException, not exceptions.Exception.

See documentation for details:


回答 1

通常,仅捕获您感兴趣的错误是最佳实践。在这种情况下,shutil.rmtree可能是OSError

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

如果要静默忽略该错误,则可以执行以下操作:

try:
    shutil.rmtree(path)
except OSError:
    pass

为什么?说您(以某种方式)不小心将整数而不是字符串传递给函数,例如:

shutil.rmtree(2)

它将给出错误“ TypeError:强制转换为Unicode:需要字符串或缓冲区,找到int” -您可能不想忽略它,这可能很难调试。

如果您确实想忽略所有错误,请抓住Exception而不是仅仅except:声明。同样,为什么呢?

不指定异常会捕获所有异常,包括SystemExit例如sys.exit()使用的异常:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

将此与以下内容进行比较,即可正确退出:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

如果您想编写更好的行为代码,则OSError异常可以表示各种错误,但是在上面的示例中,我们仅想忽略Errno 2,因此我们可以更加具体:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

It’s generally considered best-practice to only catch the errors you are interested in. In the case of shutil.rmtree it’s probably OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

If you want to silently ignore that error, you would do:

try:
    shutil.rmtree(path)
except OSError:
    pass

Why? Say you (somehow) accidently pass the function an integer instead of a string, like:

shutil.rmtree(2)

It will give the error “TypeError: coercing to Unicode: need string or buffer, int found” – you probably don’t want to ignore that, which can be difficult to debug.

If you definitely want to ignore all errors, catch Exception rather than a bare except: statement. Again, why?

Not specifying an exception catches every exception, including the SystemExit exception which for example sys.exit() uses:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Compare this to the following, which correctly exits:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

If you want to write ever better behaving code, the OSError exception can represent various errors, but in the example above we only want to ignore Errno 2, so we could be even more specific:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

回答 2

当您只想尝试捕获而不处理异常时,如何在Python中执行呢?

这取决于您所说的“处理”。

如果您打算不采取任何措施就将其捕获,则发布的代码将起作用。

如果您是想对异常采取措施而又不阻止异常上升,那么您需要这样的东西:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

When you just want to do a try catch without handling the exception, how do you do it in Python?

It depends on what you mean by “handling.”

If you mean to catch it without taking any action, the code you posted will work.

If you mean that you want to take action on an exception without stopping the exception from going up the stack, then you want something like this:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

回答 3

首先,我从这个话题中引述杰克·奥康纳的答案。引用的线程已关闭,所以我在这里写:

“ Python 3.4中引入了一种新的方法:

from contextlib import suppress

with suppress(Exception):
    # your code

这是添加了它的提交:http : //hg.python.org/cpython/rev/406b47c64480

这是作者Raymond Hettinger,讨论了这一点以及其他各种Python热度:https ://youtu.be/OSGv2VnC0go ? t = 43m23s

我对此的补充是Python 2.7等效项:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

然后像在Python 3.4中一样使用它:

with ignored(Exception):
    # your code

First I quote the answer of Jack o’Connor from this thread. The referenced thread got closed so I write here:

“There’s a new way to do this coming in Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

Here’s the commit that added it: http://hg.python.org/cpython/rev/406b47c64480

And here’s the author, Raymond Hettinger, talking about this and all sorts of other Python hotness: https://youtu.be/OSGv2VnC0go?t=43m23s

My addition to this is the Python 2.7 equivalent:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Then you use it like in Python 3.4:

with ignored(Exception):
    # your code

回答 4

为了完整性:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

还要注意,您可以像这样捕获异常:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

…并重新引发如下异常:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

…来自python教程的示例。

For completeness:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

Also note that you can capture the exception like this:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

…and re-raise the exception like this:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

…examples from the python tutorial.


回答 5

如何正确忽略异常?

有几种方法可以做到这一点。

但是,示例的选择具有一个不包含一般情况的简单解决方案。

特定于示例:

代替

try:
    shutil.rmtree(path)
except:
    pass

做这个:

shutil.rmtree(path, ignore_errors=True)

这是特定于的论点shutil.rmtree。您可以通过执行以下操作来查看有关此操作的帮助,并且您还将看到它还允许错误处理功能。

>>> import shutil
>>> help(shutil.rmtree)

由于这仅涵盖了示例的狭义情况,因此我将进一步说明如果这些关键字参数不存在,该如何处理。

一般的做法

由于上面仅涵盖了示例的狭义情况,因此我将进一步演示如果这些关键字参数不存在,该如何处理。

Python 3.4的新功能:

您可以导入suppress上下文管理器:

from contextlib import suppress

但只禁止最具体的exceptions:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

您将默默地忽略FileNotFoundError

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

文档

与其他任何完全抑制异常的机制一样,此上下文管理器仅应用于涵盖非常具体的错误,在这些错误中,静默地继续执行程序是正确的做法。

请注意,suppress并且FileNotFoundError仅在Python 3中可用。

如果您还希望代码也可以在Python 2中运行,请参阅下一节:

Python 2和3:

当您只想尝试/exceptions而不处理异常时,如何在Python中进行呢?

以下是正确的方法吗?

try :
    shutil.rmtree ( path )
except :
    pass

对于与Python 2兼容的代码,这pass是不执行操作的正确方法。但是,当你做一个光秃秃的except:,这是一样的做except BaseException:,其中包括GeneratorExitKeyboardInterrupt,和SystemExit,一般来说,你不想要赶上那些东西。

实际上,在命名异常时应尽可能具体。

这是Python(2)异常层次结构的一部分,如您所见,如果您捕获了更多常规异常,则可以隐藏您没有想到的问题:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

您可能想在这里捕获OSError,也许您不关心的异常是没有目录。

我们可以从库中获取特定的错误号errno,如果没有该错误号,则重新引发:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

请注意,不加薪将引发原始异常,在这种情况下,这可能就是您想要的。简明扼要,因为pass在异常处理中我们实际上不需要显式地使用代码:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

How to properly ignore Exceptions?

There are several ways of doing this.

However, the choice of example has a simple solution that does not cover the general case.

Specific to the example:

Instead of

try:
    shutil.rmtree(path)
except:
    pass

Do this:

shutil.rmtree(path, ignore_errors=True)

This is an argument specific to shutil.rmtree. You can see the help on it by doing the following, and you’ll see it can also allow for functionality on errors as well.

>>> import shutil
>>> help(shutil.rmtree)

Since this only covers the narrow case of the example, I’ll further demonstrate how to handle this if those keyword arguments didn’t exist.

General approach

Since the above only covers the narrow case of the example, I’ll further demonstrate how to handle this if those keyword arguments didn’t exist.

New in Python 3.4:

You can import the suppress context manager:

from contextlib import suppress

But only suppress the most specific exception:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

You will silently ignore a FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

From the docs:

As with any other mechanism that completely suppresses exceptions, this context manager should be used only to cover very specific errors where silently continuing with program execution is known to be the right thing to do.

Note that suppress and FileNotFoundError are only available in Python 3.

If you want your code to work in Python 2 as well, see the next section:

Python 2 & 3:

When you just want to do a try/except without handling the exception, how do you do it in Python?

Is the following the right way to do it?

try :
    shutil.rmtree ( path )
except :
    pass

For Python 2 compatible code, pass is the correct way to have a statement that’s a no-op. But when you do a bare except:, that’s the same as doing except BaseException: which includes GeneratorExit, KeyboardInterrupt, and SystemExit, and in general, you don’t want to catch those things.

In fact, you should be as specific in naming the exception as you can.

Here’s part of the Python (2) exception hierarchy, and as you can see, if you catch more general Exceptions, you can hide problems you did not expect:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

You probably want to catch an OSError here, and maybe the exception you don’t care about is if there is no directory.

We can get that specific error number from the errno library, and reraise if we don’t have that:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Note, a bare raise raises the original exception, which is probably what you want in this case. Written more concisely, as we don’t really need to explicitly pass with code in the exception handling:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

回答 6

当您只想尝试捕获而不处理异常时,如何在Python中执行呢?

这将帮助您打印出异常是什么(例如,在不处理异常的情况下尝试捕获并打印异常。)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

When you just want to do a try catch without handling the exception, how do you do it in Python?

This will help you to print what the exception is:( i.e. try catch without handling the exception and print the exception.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

回答 7

try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

仅供参考,else子句可以在所有异常之后执行,并且仅在try中的代码不会引起异常的情况下才会运行。

try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

FYI the else clause can go after all exceptions and will only be run if the code in the try doesn’t cause an exception.


回答 8

我需要忽略多个命令中的错误,fuckit做到了

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

I needed to ignore errors in multiple commands and fuckit did the trick

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

回答 9

在Python中,我们处理与其他语言相似的异常,但是区别在于语法上有些差异,例如,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

In Python, we handle exceptions similar to other language, but the difference is some syntax difference, for example,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

回答 10

我通常只是这样做:

try:
    doSomething()
except:
    _ = ""

I usually just do:

try:
    doSomething()
except:
    _ = ""