2017-07-18 154 views
-1

这是这样的惯用/ pythonic做还是有更好的方法吗?我希望所有错误都能在日志中记录,以防万一我无法访问控制台输出。此外,我想中止这种代码路径,以防出现问题。日志记录刚刚出现异常

try: 
     with open(self._file_path, "wb") as out_f: 
      out_f.write(...) 
      ... 
    except OSError as e: 
     log("Saving %s failed: %s" % (self._file_path, str(e))) 
     raise 

编辑:这个问题是关于在正确的地方处理异常/正确的成语。这不是关于logging类。

+0

[使用日志python类写入文件?](https://stackoverflow.com/questions/6386698/using-the-logging-python-class-to-write-toa-a-文件) –

+0

更新了问题 – VladimirLenin

+0

我并不真的在这里得到降低票数和结束选票。就我而言,这是一个非常明智的问题,而且绝对不是“基于意见”。 –

回答

1

一个经过验证的工作方案是在应用程序代码的顶层有一个通用的except子句,以确保任何未处理的错误都会被记录下来(并且会重新提出) - 同时它还使您有机会尝试并在崩溃之前进行一些清理)

一旦你有了这个,在你的代码中添加特定的“日志和重新刷新”异常处理程序是有意义的,如果你想在日志消息中捕获更多的上下文信息,如您的片段示例。这意味着异常可能会最终记录两次,但这很难,也是问题。

如果你真的是Python的(或者,如果你珍惜你的错误日志),使用stdlib's logging module和它的logger.exception()方法,将自动地完整回溯添加到日志。

日志记录模块的一些(其他)好处是能够从日志记录调用中解耦日志记录配置(应该由应用程序本身处理,并且可以非常细化)(这通常发生在库代码级别),与编写良好的库的兼容性(已经使用logging,因此您只需配置记录器即可从第三方库获取信息 - 这实际上可以节省您的屁股),并且可以使用不同的日志记录机制(根据日志源和严重性以及部署环境,将stderr,将文件,syslog,通过电子邮件警报发送给任何人,而且不限于单个处理程序)。

更新:

你会说什么再提高相同的异常(如实例),或者重新提高自定义异常(MyLibException),而不是原单?

这确实是一个常见的模式,但矫枉过正,要小心 - 你只需要针对实际预期异常,在那里你真的知道事业做到这一点。一些异常类可能有不同的原因 - 比如OSError,'IOError and RuntimeError - so never assume anything about what really caused the exception, either check it with a decently robust condition (for example the .errno field for IOError`)或让异常传播。我曾经浪费了几个小时试图理解为什么一些lib在错误的输入文件中抱怨,当真正的原因是权限问题时(我发现它跟踪了库代码...)。

这种模式的另一个可能的问题是(至少在Python2中)你将失去原来的异常和回溯,所以最好在引发你自己的异常之前正确记录它们。 IIRC Python3有一些机制可以以更简洁的方式处理这种情况,让您保留一些原始的异常信息。

+0

感谢您的详细回复。关于重新提出相同的异常(如示例中)或重新提升自定义异常(MyLibException)而不是原始异常,您会说些什么?第二种选择让我能够缩小可能出现的例外情况,这些例外情况是由我的图书馆故意产生的。它还可以区分图书馆已知的错误。 – VladimirLenin

+0

@VladimirLenin比较我编辑的答案。 –