百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文
临时起意的python启动方式,竟然令线上项目接近崩溃

临时起意的python启动方式,竟然令线上项目接近崩溃

  • 网站名称:临时起意的python启动方式,竟然令线上项目接近崩溃
  • 网站分类:技术文章
  • 收录时间:2025-07-11 22:38
  • 网站地址:

进入网站

“临时起意的python启动方式,竟然令线上项目接近崩溃” 网站介绍

杂谈

小卡公司里有一个线上项目,因为是公司内部使用的项目,因此我们会时不时更新系统,来添加一些功能。

这次添加了一个文件解析的功能,我们的传感器采集仪设备有很多类型,它们保存的数据格式都不同,因此解析起来会比较麻烦, 每种格式都准备了一个解析工具

这次就是为了解决这个麻烦,写了一个可以根据数据格式的不同,自动选择解析工具的方法,这样就可以一个入口解析各种文件,而无需单独选择解析工具来调用。

我们的代码启动方式非常简单就是:

python xxx.py

这次小卡在逛技术论坛的时候,偶然看到 -O 的启动方式,据说更适合生产环境,因此我就将线上服务改为了:

python -O xxx.py

没想到,这次改动带来了服务崩溃,同事们都一个个发来钉钉问询,与我一起开发系统的小伙伴也立即投入查看代码是否有bug。

一、寻找bug,发现真相

我和开发小伙伴在服务上线前已经做过比较细致的测试,虽然我们公司没有全职测试,但毕竟不算是特别大的系统改动,我们也算是比较全面进行过测试才上线。

我们在本地开启服务运行,并没出现线上的崩溃情况,这就更让我们疑惑了。

好在其他使用系统的同事发来了很多崩溃的截图,终于被我们找到了一个切入点:

def send_msg(string):
    # 这个方法会发送到前端,提示错误信息
    print(string)
    ...

def divide(a, b):
    assert b != 0, send_msg('除数不能为零')
    return a / b

我们的系统获取到传感器的数据后,需要做大量运算,为了防止出现除以 0 的情况,我的另一名负责这个项目的小伙伴就写了上面类似的写法,当出现类似情况,就会发送提示信息到前端。

但现在同事使用系统时,只发现程序无法执行,但没有任何提示,所以服务就出现了崩溃。

二、assert的使用和利弊

assert 是python中的一个关键字,它可以用来断言条件的真假,如果为假,则抛出 AssertionError 异常:

assert 1 != 1

我们还可以在抛出 AssertionError 异常时进行其他操作,就如之前的代码:

def send_msg(string):
    # 这个方法会发送到前端,提示错误信息
    print(string)
    ...

def divide(a, b):
    assert b != 0, send_msg('除数不能为零')
    return a / b

优势

assert 的优势就是写法上带来了便捷,它能够在一行内解决判断问题,而如果正常写,那么就得换行:

def send_msg(string):
    # 这个方法会发送到前端,提示错误信息
    print(string)
    ...

def divide(a, b):
    if b == 0:
        send_msg('除数不能为零')
        return 
    
    return a / b

很明显就是这个优势,和我一组的小伙伴比较中意这个写法,基本上他的判断都用了这个方式。

弊端

该方式在大量使用的情况下,可能会带来性能的问题。

但最主要的是,如果使用了 -O 来启动程序,那么python将忽略 assert ,因此出现了我们线上服务崩溃,而本地测试没有问题的情况。

python官网的说明

可以看到官网已经说明,当 -O 使用时,if __debug__ 和 assert 都会被移除,因此 assert 更适合在开发阶段使用,而不是在生产环境。

三、另辟蹊径

既然 assert 不适合在生产环境使用,又不想失去这样便捷的写法,那么我们可以自己来实现一个类似的方法:

def my_assert(condition, message):
    if not condition:
        raise AssertionError(message)

以后我们就可以通过以下的写法来进行替换:

def send_msg(string):
    # 这个方法会发送到前端,提示错误信息
    print(string)
    ...


def divide(a, b):
    my_assert(b != 0, send_msg('除数不能为零'))

    return a / b

最终我们使用了自定义方法,然后进行全局的文本替换,将原来的 assert 全部替换为我们自己的自定义方法完美解决了这次危机。

四、结尾

虽然最终解决了问题,但又一次验证了一个真理:能稳定运行的系统,千万不要随意修改运行方式或环境!