【问题标题】:Will the uncaught Python exception lead to memory lead or other issues?未捕获的 Python 异常会导致内存不足或其他问题吗?
【发布时间】:2019-02-19 11:00:04
【问题描述】:

我的团队内部有一个使用自动化脚本的内部代码块的争论。

以下函数发出网络请求并返回它得到的结果。

网络请求有时会因为 IOError 而失败,但如果代码重试,它将能够连接并再次获得结果。所以代码有一个重试机制来处理这样的错误。

但有时会发生其他错误(例如超时或其他错误)。从需求的角度来看,对于此类问题,我们应该以错误代码退出脚本,以便调用程序知道脚本有问题,并说邮件工程师让他们处理。

代码如下:

def my_func():
    retry_times = 5
    sleep_time = 5
    for i in range(0, 6)
        try:
            result = network_request()
            break
        except IOError as err:
            if i == retry_times:
                log.error
                raise
            else:
                log.warning("Request failed, sleep %s seconds and retry <%s/%s>"
                            % (sleep_time, i, retry_times))
    return result

但是我们的一位团队成员认为,我们应该捕获所有剩余的异常,永远不要让异常被抛出到最外层的代码,最后让脚本以错误代码退出并打印堆栈跟踪打印。

他称之为“异常泄漏”,这违反了常见的编码规则。这是他的代码(带有“# added code line”的行是更改的行):

def my_func():
    retry_times = 5
    sleep_time = 5
    for i in range(0, 6)
        try:
            result = network_request()
            break
        except IOError as err:
            if i == retry_times:
                log.error
                raise
            else:
                log.warning("Request failed, sleep %s seconds and retry <%s/%s>"
                            % (sleep_time, i, retry_times))
        except Exception:  # Added code line
            log.error("Error happened: %s" % err)  # Added code line
            exit(1)
    return result

我说他在做 Python 刚刚做过的事情:

  1. 打印错误日志。
  2. 存在具有非零退出代码的脚本

但他争辩说:“你怎么知道 Python 在捕获异常时什么也没做?”、“留下未捕获的异常会导致内存泄漏”、“任何设计良好的程序都不会将未捕获的异常留到最后,它是常识”。

这让我很困惑,因为我从未听说过这种“常识”,尤其是对于 Python(不确定 C++ 是否具有这种“常识”)。我用谷歌搜索了这个话题,发现甚至没有人问过这样的问题。我从一开始就知道异常处理的原理是:

  1. 处理您的代码能够处理的异常。
  2. 如果您无法处理这些异常,请向外部范围提出这些异常。

在这种情况下,由于该脚本是内部使用自动化脚本,当发生此类问题时,打印详细的堆栈跟踪并以非零错误代码退出脚本正是我们想要的,导致代码无法处理此类问题所以它应该最终向工程师提出这个问题。

添加捕获未知异常的行,打印错误日志,然后以非零错误代码退出脚本,就像重复地做已经完成的事情。

所以我在这里问: 1.“将未捕获的异常留到最后并最终导致脚本退出”会导致任何诸如“内存泄漏”之类的问题吗? 2. Python编码规则中是否有这样的“常识”,不留下任何未捕获的异常,提供“打印错误日志”和“以非零代码退出”正是脚本想要做的。

【问题讨论】:

  • 未捕获的异常会终止程序,所以谁在乎呢?不咳嗽泛型异常(如Exception)是一种很好的编程风格。 -- 通过退出程序,内核将释放所有资源(内存、文件、网络等) -- BTW 内存分配应该是最小的,所以它只是内部内存分配,可能永远不会要求内核分配其他大内存用于后续内存分配的缓冲区)
  • 不相关,但你不应该在try 块内return result 避免重复network_request() 吗?无论如何,对由于未捕获的异常导致的内存泄漏持怀疑态度。未捕获的异常只会终止程序,程序运行时会发生泄漏,并且不会释放不需要的资源。
  • @nicola 原始程序在 network_request() 之后确实有一个“中断”,但我错过了在这里添加它(我现在才添加它)所以不用担心。

标签: python memory-leaks exception-handling coding-style


【解决方案1】:

这取决于您的其他代码。许多框架(例如 Django)都有一个设置变量DEBUG。如果设置为真实,相关数据将被披露。如果不是,则向用户显示 404 错误。

如果您使用的是 linter,它会告诉您捕获未指定的异常是一种不好的做法

【讨论】:

    猜你喜欢
    • 2013-12-09
    • 2016-04-21
    • 1970-01-01
    • 2015-05-31
    • 2014-06-07
    • 1970-01-01
    • 2012-12-15
    • 2018-08-07
    • 1970-01-01
    相关资源
    最近更新 更多