【问题标题】:pythonic way of raising an error within the try block在try块中引发错误的pythonic方法
【发布时间】:2012-09-25 07:14:12
【问题描述】:

我有一个方法可以检查一些东西并且可以

  • 自身引发异常
  • 返回真
  • 返回错误

我想正确地捕获异常以自己提出一个异常,但如果测试返回 False。这样做的错误方法是

try:
    if not check():
        raise MyException()
except:
    raise MyException()

因为第一个MyExceptionexcept 之后再次被捕获。正确处理此问题的一种方法是

try:
    flag = check()
except:
    raise MyException()
else:
    if not flag:
        raise MyException()

这是处理这种情况的唯一方法,还是有另一种更有效的方法来处理它,摆脱 flag 变量?

【问题讨论】:

  • 首先:不要使用毯子except:捕捉,总是只捕捉特定异常。
  • @avasal:是什么让你认为 OP 不知道 raise
  • 您应该添加在 check() 中引发的异常,因为从答案中可以看出:有几种方法可以做到这一点。
  • 是的,通常情况下的特定异常除外。但是当您在服务器上运行某些东西时,您不希望服务器因错误而停止,您希望将任何错误传播给客户端。

标签: python exception-handling try-catch


【解决方案1】:

你不应该使用 except: 因为它会捕获所有异常,包括 SystemExit,你应该这样做:

try:
    if not check():
        raise MyNewException()
except ExceptionRaisedByCheck:
    raise MyNewException()

如果来自 check() 的异常与您要引发的异常相同,则应该更改它。

编辑:如果异常相同,您也可以简单地执行此操作(Mark Byers 在他的回答中有这个,但现在已经消失了):

if not check():
    raise TheSameException()

这将传播异常或在 False 时引发。

【讨论】:

  • +1 这并没有严格回答这个问题,但恕我直言,这个问题并没有经过深思熟虑。这几乎肯定比 OP 错误地认为是个好主意要好,尽管没有更多背景知识很难判断他在做什么。
  • @MarkByers 你删除了你的答案?我编辑了我的答案以添加您的部分答案,因为这确实是最简单的解决方案,我之前没有考虑过。正如你所说,很难说目标是什么。
【解决方案2】:

在python 3.3中,你可以使用新的contextlib.ExitStack context manager

with ExitStack() as stack:
    stack.callback(lambda: raise MyException)

    if check():
        stack.pop_all()

这将引发MyException除非您使用pop_all() 清除堆栈回调。

您可以将其编码为自定义上下文管理器:

from contextlib import ExitStack

class ExceptionUnlessCancelled(ExitStack):
    def __init__(self, exception, *args, **kw):
        super(Callback, self).__init__()
        self.exception = exception
        self.callback(self.raiseException, *args, **kwds)

    def raiseException(self, *args, **kw):
        raise self.exception(*args, **kw)

    def cancel(self):
        self.pop_all()

with ExceptionUnlessCancelled(MyException) as exc:
    if check():
        exc.cancel()

【讨论】:

  • 似乎有点过度设计,但仍然是有趣的解决方案!
  • @SebastianBlask:我认为上下文管理器是处理复杂异常情况的好方法。 OP 的情况已经针对这个问题进行了简化,谁知道围绕检查还有多少代码?
【解决方案3】:
try:
   # whatever
except MyException:
   raise # reraise it
except Exception as e:
   raise MyException(some_info(e)) # unify user-visible exception type

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-13
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多