Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在重新尝试代码时,异常处理非常好_Python_Exception_Exception Handling_Code Formatting - Fatal编程技术网

Python 在重新尝试代码时,异常处理非常好

Python 在重新尝试代码时,异常处理非常好,python,exception,exception-handling,code-formatting,Python,Exception,Exception Handling,Code Formatting,我有一些测试用例。测试用例依赖于需要时间计算的数据。为了加快测试速度,我缓存了数据,这样就不必重新计算 我现在有了查看缓存数据的foo()。我不能提前知道它将看到什么,因为这在很大程度上取决于测试用例 如果一个测试用例由于找不到正确的缓存数据而失败,我不希望它失败——我希望它计算数据,然后再试一次。我也不知道它会引发什么异常,特别是导致数据丢失的原因 我现在的代码如下所示: if cacheExists: loadCache() dataComputed = False else

我有一些测试用例。测试用例依赖于需要时间计算的数据。为了加快测试速度,我缓存了数据,这样就不必重新计算

我现在有了查看缓存数据的
foo()
。我不能提前知道它将看到什么,因为这在很大程度上取决于测试用例

如果一个测试用例由于找不到正确的缓存数据而失败,我不希望它失败——我希望它计算数据,然后再试一次。我也不知道它会引发什么异常,特别是导致数据丢失的原因

我现在的代码如下所示:

if cacheExists:
    loadCache()
    dataComputed = False
else:
    calculateData()
    dataComputed = True

try:
    foo()
except:
    if not dataComputed:
        calculateData() 
        dataComputed = True
        try:
            foo()
        except:
            #error handling code
    else:
        #the same error handling code

重新构造此代码的最佳方法是什么?

在进行调用之前,是否有方法告诉您是否要执行foobetter()?如果您遇到异常,应该是因为发生了意外(异常!)。不要将异常用于流控制。

使用一揽子异常通常不是一个好主意。你认为那里会出现什么样的例外情况?这是一个键错误,属性错误,类型错误

一旦确定了要查找的错误类型,您可以使用类似于
hasattr()
中的
操作符或许多其他东西来测试您的情况,然后再处理异常


这样,您就可以清理逻辑流,并将异常处理保存到真正发生故障的地方

> P>我不同意现有答案中的关键建议,基本上归结为处理Python中的异常,如C++或java,这不是Python中的首选样式,通常有一个好的老想法:“最好是请求原谅而不是许可”。(尝试一个操作并处理异常(如果有),而不是通过彻底的初步检查来模糊代码的主要流程并导致开销)。我同意Gabriel的观点,即除了
之外,一个简单的
几乎从来都不是一个好主意(除非它所做的只是某种形式的日志记录,然后是一个
提升
,让异常传播)。因此,假设您有一个包含所有异常类型的元组,并且您希望以相同的方式处理这些异常类型,例如:

expected_exceptions = KeyError, AttributeError, TypeError
并始终使用
除预期的例外情况外:
而不是裸
除:

因此,有了这些,一个稍微不那么重复的方法就是:

try:
    foo1()
except expected_exceptions:
    try:
        if condition:
            foobetter()
        else:
            raise
    except expected_exceptions:
        handleError()
另一种方法是使用辅助函数包装try/except逻辑:

def may_raise(expected_exceptions, somefunction, *a, **k):
  try:
    return False, somefunction(*a, **k)
  except expected_exceptions:
    return True, None
这样的助手通常在几种不同的情况下都很有用,因此在项目的“实用程序”模块中有这样的东西是很常见的。现在,对于您的情况(没有参数,没有结果),您可以使用:

failed, _ = may_raise(expected_exceptions, foo1)
if failed and condition:
  failed, _ = may_raise(expected_exceptions, foobetter)
if failed:
  handleError()

我认为它更线性,因此更简单。这种通用方法的唯一问题是,像
may_raise
这样的辅助函数不会强迫您以某种方式处理异常,因此您可能会忘记这样做(就像使用返回码而不是异常来指示错误一样,这些返回值很容易被错误地忽略);因此,请谨慎使用…!-)

有时没有很好的方法来表示流,这很复杂。但是这里有一种方法可以只在一个位置调用foo(),并且只在一个位置进行错误处理:

if cacheExists:
    loadCache()
    dataComputed = False
else:
    calculateData()
    dataComputed = True

while True:
    try:
        foo()
        break
    except:
        if not dataComputed:
            calculateData()
            dataComputed = True
            continue 
        else:
            #the error handling code
            break
你可能不喜欢这个循环,YMMV

或:


我喜欢Alex Martelli提出的替代方法

你认为使用函数列表作为may_raise的参数怎么样?这些函数将一直执行到一个函数成功为止

这是密码

def foo(x): raise Exception("Arrrgh!") return 0 def foobetter(x): print "Hello", x return 1 def try_many(functions, expected_exceptions, *a, **k): ret = None for f in functions: try: ret = f(*a, **k) except expected_exceptions, e: print e else: break return ret print try_many((foo, foobetter), Exception, "World") def foo(x): 引发异常(“arrgh!”) 返回0 def(x): 打印“你好”,x 返回1 def try_MUN(函数、预期的_异常、*a、**k): ret=无 对于函数中的f: 尝试: ret=f(*a,**k) 除预期的例外情况外,e: 打印e 其他: 打破 回程网 打印try\u many((foo,foobetter),例外,“World”) 结果是

Arrrgh! Hello World 1 啊! 你好,世界 1.
为什么你要在第一个例外中检查一个条件?从下一次尝试开始/然后在第二个例外中,打破它以处理错误()?哦,嗯…我明白你的意思。我会尝试它不,因为如果条件为假,我将毫无例外地处理(因为它将被捕获)这根本不是Python中异常的工作方式。语言运行库本身为非异常事件抛出异常。我喜欢这个想法。我可能会同意这样的想法。呵呵,这基本上是使用循环来创建延续/转到。有趣的想法 Arrrgh! Hello World 1