如何让python优雅地失败?

Fur*_*lon 14 python

我只是想知道如何在所有可能的错误中以用户定义的方式使python失败.

例如,我正在编写一个处理(大)项目列表的程序,而某些项目可能不是我定义的格式.如果python检测到错误,它当前只会发出一个丑陋的错误消息并停止整个过程.但是,我希望它只是将错误输出到某个地方以及某些上下文,然后转到下一个项目.

如果有人可以帮助我,我将不胜感激!

非常感谢!

贾森

pir*_*iro 25

以下是我经常在我的琐碎脚本和中型应用程序中使用的一些基本策略.

提示1:在有意义继续处理的每个级别捕获错误.在你的情况下,它可能在循环内部.您不必保护每一行或每一个函数调用,而只需保护它能够在错误中生存的地方.

技巧2:使用日志记录模块以可配置的方式报告发生的事件,与在较大的应用程序中将模块与其他模块组合的方式无关.开始在模块中导入根记录器,然后,在几个不同的地方使用它,您最终可能会找到一个更合理的日志记录层次结构.

import logging
logger = logging.getLogger()

for item in items:
    try:
        process(item)
    except Exception, exc:
        logger.warn("error while processing item: %s", exc)
Run Code Online (Sandbox Code Playgroud)

提示3:定义"应用程序异常",最终您可能希望定义此类异常的层次结构,但在需要时可以更好地发现此异常.当您处理的数据不符合您的预期或发出不一致的情况时,使用此类异常来"冒泡",同时将它们与模拟域外的常规错误或问题引起的正常标准异常分开(IO错误)等等).

class DomainException(Exception):
    """Life is not what I expected"""

def process(item):
    # There is no way that this item can be processed, so bail out quickly.
    # Here you are assuming that your caller will report this error but probably
    # it will be able to process the other items.
    if item.foo > item.bar:
        raise DomainException("bad news")

    # Everybody knows that every item has more that 10 wickets, so
    # the following instruction is assumed always being successful.
    # But even if luck is not on our side, our caller will be able to
    # cope with this situation and keep on working
    item.wickets[10] *= 2
Run Code Online (Sandbox Code Playgroud)

主要功能是最外面的检查点:最后处理你的任务完成的可能方式.如果这不是shell脚本(但是例如UI应用程序中的对话框下的处理或Web应用程序中的POST之后的操作),则仅报告错误的方式发生更改(并且使用日志记录方法完全分离实现从其界面处理).

def main():
    try:
        do_all_the_processing()
        return 0
    except DomainException, exc:
        logger.error("I couldn't finish. The reason is: %s", exc)
        return 1
    except Exception, exc:
        logger.error("Unexpected error: %s - %s", exc.__class__.__name__, exc)
        # In this case you may want to forward a stacktrace to the developers via e-mail
        return 1
    except BaseException:
        logger.info("user stop") # this deals with a ctrl-c
        return 1

if __name__ == '__main__':
    sys.exit(main())
Run Code Online (Sandbox Code Playgroud)


dF.*_*dF. 8

丑陋的错误消息意味着引发了异常.你需要捕获异常.

一个好的起点是Python教程的异常部分.

基本上你需要将代码包装在这样的try...except块中:

try:
    do_something_dangerous()
except SomeException:
    handle_the_error()
Run Code Online (Sandbox Code Playgroud)