我是靠谱客的博主 温暖冬瓜,最近开发中收集的这篇文章主要介绍调试断言失败_一日一技:python中的断言,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

e5cde2ff95a209635e1effa1e83f35aa.png

一、使用python中的断言来自动检测python程序中的错误,让程序更加可靠且更易于调试

从根本上来说,python中的断言语句是一种调试工具,用来测试某个断言条件,如果断言条件为True,则程序将继续正常执行;但如果断言条件为假False,则会引发AssertionError异常并显示相关的错误消息。

示例:

假设你需要使用python构建在线商城,为了添加打折优惠功能,你编写了下面这个apply_discount函数:

def apply_discount(product, discount):
    price = int(product['price'] * (1 - discount))
    assert 0 <= price <= product['price']    # 断言
    return price

注意到assert语句了吗?这条语句确保在任何情况下,通过该函数计算的折后价格不低于0,也不会高于产品原价。

下面创建一个示例产品,一双价格为1000元的鞋子,现在如果为这双鞋打五折,则价格应该变为500,对该函数进行测试:

def apply_discount(product, discount):
    price = int(product['price'] * (1 - discount))
    assert 0 <= price <= product['price']
    return price


if __name__ == "__main__":
    shoes = {
        "name": "鞋子",
        "price": 1000,
    }
    price = apply_discount(shoes, 0.5)
    print(price)

6b4058f70da8075d84a066033cea3853.png

还不错,接着我们再尝试使用一些无效的折扣,比如200%的”折扣“会让商家向顾客付钱:

5c2901be648c62954be17723c4a266dc.png

从上面的信息可以看到,当尝试使用无效的折扣时,程序会停止并触发一个AssertionError。发生这种情况是因为200%的折扣违反了在apply_discount函数中设置的断言条件,从异常栈的跟踪信息中还能得知断言验证失败的具体位置。

二、为什么不用普通的异常来处理?

断言是为了告诉开发人员程序中发生了不可恢复的错误,对于可以预料的错误(如未找到相关文件),用户可以予以纠正或重试,断言并不是为此而生的。

如果程序没有bug,那么这些断言条件永远也不会触发,但如果违反了断言条件,程序就会崩溃并报告断言错误,告诉开发人员究竟违反了哪个“不可能”的情况,这样可以更轻松的追踪和修复程序中的bug。python中的断言语句是一种调试辅助功能,不是用来处理运行时错误的机制,使用断言的目的是让开发人员更快速的找到可能导致bug的根本原因,除非程序中存在bug,否则绝不会抛出断言错误。

三、assert语法及使用注意事项

语法:

assert <断言判断条件> [,"错误提示消息"]

其中的错误提示消息是可选的,如果加了错误提示消息,则会在抛出异常时,同异常消息一同展示,如:

a0b0804912beacf680c2dae022e694c4.png

注意事项:

在Python中使用断言时,需要注意,第一:断言会给应用程序带来安全风险和bug;第二:容易写出很多无用的断言语句。

1、不用使用断言验证数据

在python中使用断言时要注意的一个重点是,若在命令行中使用-o和-oo标识,或修改CPython中的PYTHONOPTIMIZE环境变量,都会全局禁用断言。此时所有的断言语句都会无效,程序会直接略过而不处理断言,因此不会执行任何条件表达式,因此使用断言语句来快速验证输入数据非常危险。

下面用一个简单的例子说明这个问题,前面一样,假设使用Python构建一个在线商城,代码中有一个函数会根据用户的请求来删除产品,于是写下这样的实现:

def delete_product(prod_id, user):
    assert user.is_admin(), "Must be admin."
    assert store.has_product(prod_id), "Unknown product."
    store.get_product(prod_id).delete()

仔细看这个函数,如果断言被禁用后会发生什么?这个仅有三行代码的函数示例存在两个严重的问题:

(1)使用断言语句检查管理员权限很危险,如果在Python解释器中禁用了断言,这行代码则会变为空操作,不会执行权限检查,之后任何用户都可以删除产品,这可能会引发安全问题,攻击者可能会借此摧毁或严重破会在线商城中的数据。

(2)禁用断言后会跳过has_product()检查,这意味着可以使用无效的产品ID调用get_product(),这可能会导致更严重的bug,具体情况取决于程序的编写方式,在最糟糕的情况下,有人可以借此对商城发起拒绝服务攻击。例如:如果尝试删除未知产品会导致商城应用程序崩溃,那么 攻击者就可以发送大量无效的删除请求让程序无法正常工作。

那么如何避免这些问题呢?答案是绝对不要使用断言来验证数据,而是使用常规的 if 语句验证,并在必要的时候触发验证异常,如下所示:

def delete_product(prod_id, user):
    if not user.is_admin():
        raise AuthError("Must be admin.")
    if not store.has_product(prod_id):
        raise ValueError("Unknown product.")
    store.get_product(prod_id).delete()

修改后的示例还有个好处,即代码不会触发通用的AssertionError异常,而是触发与语义相关的异常,如ValueError或AuthError。

2、永不失败的断言

开发人员很容易就会添加许多总是为True的python断言,因此这些语句毫无用处,永远不会触发异常。

四、总结

尽管有这些需要注意的事项,但Python的断言依然是功能强大的调试工具,了解断言的工作方式及其使用场景有助于编写更易于维护和调试的Python程序,学习断言有助于将个人的python知识提升到新的水平。

关键要点:

  • python断言语句是一种测试某个条件的调试辅助功能,可作为程序的内部自检
  • 断言应该只用于帮助开发人员识别bug,它不是用于处理运行时异常的机制
  • 设置解释器可全局禁用断言

最后

以上就是温暖冬瓜为你收集整理的调试断言失败_一日一技:python中的断言的全部内容,希望文章能够帮你解决调试断言失败_一日一技:python中的断言所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部