Python 中异常处理程序的成本

2025-03-05 09:16:00
admin
原创
52
摘要:问题描述:在另一个问题中,接受的答案建议用 try/except 块替换 Python 代码中的(非常便宜的)if 语句以提高性能。撇开编码风格问题,假设异常从未被触发,那么有一个异常处理程序,与没有异常处理程序,与有一个与零比较的 if 语句相比,在性能方面会有多大区别?解决方案 1:为什么不使用timei...

问题描述:

在另一个问题中,接受的答案建议用 try/except 块替换 Python 代码中的(非常便宜的)if 语句以提高性能。

撇开编码风格问题,假设异常从未被触发,那么有一个异常处理程序,与没有异常处理程序,与有一个与零比较的 if 语句相比,在性能方面会有多大区别?


解决方案 1:

为什么不使用timeit模块来测量呢?这样你就能知道它是否与你的应用程序相关。

好的,我刚刚尝试了以下操作(在 Windows 11 上使用 Python 3.11.1):

import timeit

statements=["""\ntry:
    b = 10/a
except ZeroDivisionError:
    pass""",
"""\nif a:
    b = 10/a""",
"b = 10/a"]

for a in (1,0):
    for s in statements:
        t = timeit.Timer(stmt=s, setup='a={}'.format(a))
        print("a = {}
{}".format(a,s))
        print("%.2f usec/pass
" % (1000000 * t.timeit(number=100000)/100000))

结果:

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.06 usec/pass

a = 1
if a:
    b = 10/a
0.05 usec/pass

a = 1
b = 10/a
0.03 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.27 usec/pass

a = 0
if a:
    b = 10/a
0.02 usec/pass

a = 0
b = 10/a
Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
  File "C:Python311Lib    imeit.py", line 178, in timeit
    timing = self.inner(it, self.timer)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<timeit-src>", line 6, in inner
ZeroDivisionError: division by zero

try/except如您所见,除非触发异常,否则使用子句与使用显式语句之间没有太大区别if。(当然,没有任何控制结构是最快的,尽管不是很快,而且如果出现任何问题,它会导致程序崩溃)。

将此与 2010 年获得的结果进行比较:

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.25 usec/pass

a = 1
if a:
    b = 10/a
0.29 usec/pass

a = 1
b = 10/a
0.22 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.57 usec/pass

a = 0
if a:
    b = 10/a
0.04 usec/pass

a = 0
b = 10/a
ZeroDivisionError: int division or modulo by zero

我现在使用的 PC 似乎比我当时的 PC 快了两倍。处理异常的成本似乎相同,并且“正常”操作(算术)的改进甚至比控制结构的处理还要多,但多年前的观点仍然成立:

所有这些都在同一数量级内,而且不太可能产生任何影响。只有当条件确实满足(通常)时,if版本才会明显更快。

解决方案 2:

这个问题实际上在设计和历史常见问题解答中得到了回答:

如果没有异常发生,try/except 块是非常高效的。实际上,捕获异常的代价是昂贵的。

解决方案 3:

在 Python 3.11 中,

“Zero-cost” exceptions are implemented. The cost of try statements is almost eliminated when no exception is raised. (Contributed by Mark Shannon in bpo-40222.)

https://docs.python.org/3.11/whatsnew/3.11.html#misc

解决方案 4:

这个问题很容易让人误解。如果你假设异常永远不会被触发,那么这两个代码都不是最佳代码。

如果您假设异常是作为错误条件的一部分触发的,那么您已经超出了想要最佳代码的范围(并且您可能不会像那样在细粒度级别上处理它)。

如果你将异常用作标准控制流的一部分 - 这是 Pythonic 的“请求原谅而不是许可”方式 - 那么异常将被触发,并且成本取决于异常的类型、if 的类型以及你估计异常发生的时间百分比。

解决方案 5:

问:try/catch在 Python 中 costly 吗?

使用 try catch 时我应该担心什么?有什么需要担心的吗?

这只是对已给出的答案的总结。

答:有异常时if速度会快很多。否则则不行。

@SuperNova 写道,异常的成本为零,因此它比没有异常时使用 if 语句更快。但是,处理异常的成本很高,因此:

对可能失败的事情使用 try。如果可能,避免对你知道会失败的事情使用 try。

例子:
  1. 好的例子,使用 try:

try:
    x = getdata() # an external function 
except:
    print('failed. Retrying')
  1. 不好的情况,这里 if-version 是首选:

y = f(x) # f never fails but often returns 0
try:
    z = 1 / y # this fails often
except:
    print('failed.')

# if-version
y = f(x)
if y != 0:
    z = 1 / y
else:
    print('failed.')

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3998  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2749  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   85  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   96  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   83  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用