【问题标题】:Python Exception Safe Pickle UsePython 异常安全泡菜使用
【发布时间】:2015-10-23 16:50:25
【问题描述】:

背景

我继承了包含大量try ... except: 子句的代码库。它们中的大多数都太宽泛了,调试起来很痛苦。我一直在经历并将每个更改为最合理的形式,这通常涉及删除它或指定异常。

问题

但是我有点被这个难住了:

try:
    with open(self.session_filename, "rb") as f:
        data = cPickle.loads(zlib.decompress(f.read()))
except:
    # we didn't need your file anyway!
    return

我想专门处理异常,但Python docs on Pickle 说:

pickle.UnpicklingError 异常

当解开一个问题时会引发此异常 目的。请注意,期间也可能引发其他异常 unpickling,包括(但不一定限于) AttributeErrorEOFErrorImportErrorIndexError

翻译:该方法可能会抛出任何东西!

显然它可以引发任意异常,这使得很难专门处理它们。

我怎样才能最合理地处理这种情况,同时牢记以下目标:

  1. 我想捕获由错误文件名或其他操作系统问题或错误格式导致的所有异常。
  2. 我不想过于宽泛而隐藏其他问题。
  3. 我不希望阅读实现并尝试解析所有不同的潜在异常。这将取决于实现,可能会因更新而失败,并且需要很多时间。

可能不是所有的都能实现。

【问题讨论】:

  • 如果你真的不想缩小范围(和/或这样做不相关),你可以使用except Exception:
  • “异常安全”是什么意思?您无法提前知道是否有可能在完成 unpickling 的同时从各种异常中恢复(例如,由于某种磁盘故障导致的 IOError)。你想处理哪些错误情况,你想如何处理它们?
  • @BrenBarn 异常安全,我的意思是我想处理应用程序并崩溃或继续处理除未处理异常之外的其他事情。在这种情况下,我可以假设酸洗失败并中止该方法尝试执行的操作(该方法提供了“尽力而为”)。如果不同的例外可以给我更详细的信息,我会很感兴趣。
  • @jonrsharpe 我试图避免过于宽泛的例外。所有异常方法也可以捕获,例如,来自 Ctrl+C 的 SIGINT,导致我的应用程序锁定在控制台上,并且在应该退出时不退出。 except Exception:except: 相同,并且都在 PyCharm 中发出警告(也有充分的理由!)。
  • 不,不一样;它不会捕获 Ctrl-C 等,这就是我建议它的原因。阅读文档中的异常层次结构。

标签: python python-2.7 exception-handling


【解决方案1】:

将异常分解为多个处理程序可能是您想要的,如果您需要,可以使用包罗万象的方法。

try:
    with open(self.session_filename, "rb") as f:
         data = cPickle.loads(zlib.decompress(f.read()))
except pickle.UnpicklingError as e:
    # normal, somewhat expected
    continue
except (AttributeError,  EOFError, ImportError, IndexError) as e:
    # secondary errors
    print(traceback.format_exc(e))
    continue
except Exception as e:
    # everything else, possibly fatal
    print(traceback.format_exc(e))
    return

【讨论】:

  • 谢谢!现在这对我有用。对于这个特定的代码位,我还需要为open() 捕获IOError,为zlib.decompress() 捕获zlib.error。我认为次要例外条款是针对半预期错误的。完美的妥协。
【解决方案2】:

通常我会尝试只处理在这种情况下实际上不可能的特定异常:谁知道cPickle.loads 将来会抛出什么异常。

如果无法更具体地说明异常的类型,我会尝试更具体地说明我在try ... except 中包装的代码块。对于这个例子,这可能是这样的:

with open(self.session_filename, "rb") as f:
    uncompressed_data = zlib.decompress(f.read())

try:
    data = cPickle.loads(uncompressed_data)
except cPickle.UnpicklingError:
    raise
except Exception as e:
    # Unpickling failed
    raise cPickle.UnpicklingError(repr(e))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 2016-06-16
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2010-12-02
    • 2016-11-20
    • 2015-09-13
    相关资源
    最近更新 更多