如何编写一个捕获所有异常的`try`/` except`块?

问题描述 投票:0回答:11

如何编写一个捕获所有异常的

try
/
except
块?

python exception
11个回答
1335
投票

除了裸露的

except:
子句(正如其他人所说你不应该使用),你可以简单地捕获
Exception
:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

您通常只会考虑在代码的最外层执行此操作,例如,如果您想在终止之前处理任何其他未捕获的异常。

except Exception
相对于裸露的
except
的优点是,有一些例外情况它不会捕捉到,最明显的是
KeyboardInterrupt
SystemExit
:如果你捕捉并吞下它们,那么你可能会让任何人都很难捕捉到它们。退出脚本。


760
投票

你可以,但你可能不应该:

try:
    do_something()
except:
    print("Caught it!")

但是,这也会捕获像

KeyboardInterrupt
这样的异常,而你通常不希望这样,不是吗?除非您立即重新引发异常 - 请参阅以下示例来自文档

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print("I/O error({0}): {1}".format(errno, strerror))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

181
投票

要捕获所有可能的异常,请捕获

BaseException
。它位于 Exception 类层次结构的顶部:

Python 3: https://docs.python.org/3.12/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

但正如其他人提到的,你通常不需要这个,只有在非常特殊的情况下才需要。


120
投票

您可以这样做来处理一般异常

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

65
投票

非常简单的示例,类似于此处找到的示例:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

如果您尝试捕获所有异常,请将所有代码放在“try:”语句中,代替“print“执行可能引发异常的操作。”。

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

在上面的示例中,您会按以下顺序看到输出:

1) 执行可能引发异常的操作。

2)无论是否抛出异常,执行完try语句后都会直接调用finally。

3)“抛出异常!”或“一切看起来都很棒!”取决于是否抛出异常。

希望这有帮助!


42
投票

有多种方法可以做到这一点,特别是使用 Python 3.0 及更高版本

方法1

这是简单的方法,但不推荐,因为您无法确切知道哪一行代码实际上引发了异常:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

方法2

建议使用此方法,因为它提供有关每个异常的更多详细信息。它包括:

  • 您的代码的行号
  • 文件名
  • 更详细的实际错误

唯一的缺点是需要导入tracback。

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

26
投票

我刚刚发现了这个小技巧,用于测试 Python 2.7 中的异常名称。有时我在代码中处理了特定的异常,所以我需要一个测试来查看该名称是否在已处理的异常列表中。

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

24
投票

我添加了额外的方法,可以捕获带有完整回溯的异常,这可以帮助您更多地理解错误。

Python 3

import traceback

try:
    # your code goes here
except Exception as e:
    print(e)
    traceback.print_exc()

11
投票
try:
    whatever()
except:
    # this will catch any exception or error

值得一提的是,这不是正确的 Python 编码。这也会捕获许多您可能不想捕获的错误。


8
投票

首先,有一些异常是您希望它们破坏您的代码(因为当发生此错误时您的代码将无法运行!)以及您希望静默/顺利地捕获的异常。尝试区分它们。您可能不想捕获所有异常!

其次,您可以花时间查看流程日志,而不是捕获所有内容。假设您收到了不同/第三方的异常,例如来自 GCP 等云服务提供商的异常。在日志中,您可以找到遇到的异常。然后,你可以这样做:

from google.api_core.exceptions import ServiceUnavailable, RetryError

for i in range(10):
   try:
      print("do something")

   except ValueError:
      print("I know this might happen for now at times! skipping this and continuing with my loop"

   except ServiceUnavailable:
      print("our connection to a service (e.g. logging) of gcp has failed")
      print("initializing the cloud logger again and try continuing ...") 

   except RetryError:
      print("gcp connection retry failed. breaking the loop. try again later!)
      break

对于其余的(可能发生也可能不会发生的错误),如果我遇到意外的异常,我会为我的代码崩溃留出空间!这样我就可以了解正在发生的事情并通过捕获边缘情况来改进我的代码。

如果您希望它永远不会因某种原因崩溃,例如,如果它是嵌入在您无法轻松访问的远程硬件中的代码,您可以在末尾添加通用异常捕获器:

except Exception as e:
   print(f"something went wrong! - {e}")

您还可以在此处查看 Python 3 异常层次结构。

Exception
BaseException
之间的区别在于,
Exception
不会捕获
SystemExit
KeyboardInterrupt
GeneratorExit


0
投票

除了捕获异常之外,这不是一个尝试。它是用于捕获异常并将其写入文件并重新启动脚本/程序的代码。

回到主题。 sys.excepthook 将允许您使用函数来自定义异常的处理。有关更多详细信息,请参阅使用 Python 的异常挂钩创建漂亮的回溯

我所写内容背后的想法是某种后台进程,如服务器、监控系统等。

import sys
import traceback
from datetime import datetime
from types import TracebackType
from typing import Optional

from os import startfile
from os.path import basename
from psutil import Process, process_iter


def unhandled_exception(exc_type: type, exc_value: BaseException, exc_traceback: TracebackType):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    filename = f'crash/{datetime.now().strftime("%m-%d-%Y %H.%M.%S")}.log'
    with open(filename, 'w') as crash_report:
        crash_report.write("Traceback (most recent call last):\n")
        traceback.print_tb(exc_traceback, file = crash_report)
        crash_report.write(f'{exc_type.__name__}: {str(exc_value)}')

    main: Optional[Process] = next((process for process in process_iter() if process.name() == 'python.exe' and (file for file in process.open_files() if 'main.py' in file.path)), None)

    startfile('main.py')

    if main is not None:
        main.kill()


sys.excepthook = unhandled_exception
© www.soinside.com 2019 - 2024. All rights reserved.