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
Error handling 复杂函数的Pythonic错误处理_Error Handling_Python - Fatal编程技术网

Error handling 复杂函数的Pythonic错误处理

Error handling 复杂函数的Pythonic错误处理,error-handling,python,Error Handling,Python,我想知道是否有一种python方法来处理长时间运行的函数中的错误,这些函数中的错误部分不会影响函数继续运行的能力 作为一个例子,考虑给定URL列表的函数,它递归地检索顶级URL路径下的资源和所有链接的资源。它将检索到的资源存储在本地文件系统中,该文件系统具有镜像URL结构的目录结构。本质上,这是一个页面列表的基本递归wget 此功能可能会在许多方面失败: URL可能无效或无法解析 主机可能无法访问(可能是暂时的) 本地保存可能有磁盘错误 还有什么你能想到的吗 检索或保存任何一个资源失败只会影

我想知道是否有一种python方法来处理长时间运行的函数中的错误,这些函数中的错误部分不会影响函数继续运行的能力

作为一个例子,考虑给定URL列表的函数,它递归地检索顶级URL路径下的资源和所有链接的资源。它将检索到的资源存储在本地文件系统中,该文件系统具有镜像URL结构的目录结构。本质上,这是一个页面列表的基本递归wget

此功能可能会在许多方面失败:

  • URL可能无效或无法解析
  • 主机可能无法访问(可能是暂时的)
  • 本地保存可能有磁盘错误
  • 还有什么你能想到的吗
检索或保存任何一个资源失败只会影响函数继续处理该资源以及可能与其链接的任何子资源的能力,但可以继续检索其他资源

错误处理的一个简单模型是,在第一个错误时,会引发一个适当的异常以供调用方处理。这样做的问题是它终止了函数,不允许它继续。错误可能会被修复,函数会从一开始就重新启动,但这会导致工作被重做,任何永久性错误都可能意味着我们永远无法完成

我想到的两个备选方案是:

  • 在列表中记录发生的错误,并中止处理该资源的任何子资源,但继续处理下一个资源。如果出现太多错误,可以使用阈值中止整个函数,或者尝试所有操作。调用方可以在函数完成时查询此列表,以查看是否存在任何问题
  • 调用方可以提供一个可调用的对象,该对象在每次发生错误时都会被调用。这将把记录错误的责任转移回调用者。您甚至可以指定,如果callable返回False,则处理应该停止。这将把阈值管理移到调用方
  • 用后者实现前者,提供一个错误处理对象,而不是编码前者的行为
在Python讨论中,我经常提到一些被描述为Pythonic或non-Pythonic的方法。我想知道是否有任何特殊的python方法来处理上述场景类型

Python是否包含了比异常处理的终止模型更复杂的错误处理模型,或者包含的更复杂的电池是否使用了我应该复制的错误处理模型以保持Pythonic


注意:请不要将重点放在示例上。我并不想解决这一特定领域的问题,但这似乎是一个很好的例子,这里的大多数人都会理解。

错误处理应该依赖于异常和日志记录,因此对于每个错误,都会引发异常并记录错误消息

然后在任何调用方函数级别捕获异常,如果需要,记录任何其他错误并处理该问题

如果问题没有得到完全处理,那么上层可以捕获相同的异常并执行不同的操作


在任何一个阶段中,您都可以保留某些类型异常的计数器,以便只有在出现特定数量的问题时才能执行某些操作。

我不认为在您这里讨论的级别上有一个特别明确的“Pythonic/non Pythonic”区别

在这个领域没有“一刀切”的解决方案的一个重要原因是,您想要的确切语义将是特定于问题的

  • 对于一种情况,第一次失败时中止可能就足够了
  • 另一方面,如果任何操作失败,您可能需要中止和回滚
  • 第三,您可能希望完成尽可能多的操作,只需记录并忽略故障
  • 对于第四种选择,您可能希望完成尽可能多的操作,但在最后引发异常以报告任何失败的操作
即使支持错误处理程序也不一定涵盖所有这些期望的行为——简单的每失败错误处理程序无法轻松提供中止和回滚语义,或者在最后生成单个异常。(这不是不可能的-您只需要使用一些技巧,比如传递绑定方法或闭包作为错误处理程序)

因此,您所能做的最好的事情就是在遇到错误时对典型的使用场景和期望的行为进行有根据的猜测,并相应地设计API

一个完全通用的解决方案将接受一个on错误处理程序,该处理程序在每次故障发生时都会给出,以及一个最终的“错误发生”处理程序,该处理程序使调用方有机会决定如何处理多个错误(使用一些协议允许数据从单个错误处理程序传递到最终的批处理错误处理程序)

然而,提供这样一个通用的解决方案很可能是API设计的失败。API的设计者不应该害怕就如何使用他们的API以及如何处理错误发表意见。要记住的主要事项是不要过度设计您的解决方案:

  • 如果天真的方法是足够的,不要弄乱它
  • 如果在列表中收集故障并报告单个错误就足够了,那么就这样做
  • 如果您需要在某个部分出现故障时回滚所有内容,那么就这样实现它
  • 如果存在用于自定义错误处理的真正用例,那么接受错误处理程序作为API的一部分。但是当你做这件事的时候,记住一个特定的用例,不要仅仅为了它而做。当您这样做时,如果用户没有指定一个默认处理程序,则使用一个合理的默认处理程序(这可能只是天真的“立即提升”方法)
  • def myFunction(an_arg, error_handler)
      # Do stuff
      if err_occurred:
        if isinstance(err, RuntimeError):
          error_handler.handleRuntimeError()
        elif  isinstance(err, IOError):
          error_handler.handleIOError()