Python中异常处理程序的成本


97

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

除了编码样式问题外,并假设永远不会触发异常,拥有一个异常处理程序与没有一个异常处理程序,与拥有与零比较的if语句相比,在性能方面有何不同?


6
当您测量它时,您学到了什么?
S.Lott


如果进入零件以外的控制机会较少,则使用try / except;如果机会较多,则使用if / else。
shadow0359 '16

Answers:


112

为什么不使用timeit模块进行测量?这样,您可以查看它是否与您的应用程序相关。

好,所以我已经尝试了以下方法:

import timeit

statements=["""\
try:
    b = 10/a
except ZeroDivisionError:
    pass""",
"""\
if 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 = {}\n{}".format(a,s))
        print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000))

结果:

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

因此,正如预期的那样,没有任何异常处理程序会稍快一些(但在发生异常时会炸毁您的脸),并且只要不满足条件,它try/except就会比显式的要快if

但这一切都在同一数量级内,并且无论哪种方式都不太重要。仅当实际满足条件时,if版本才会明显更快。


3
有趣。所以try/exceptif a != 0
Thilo

10
啊,这是一个很好的选择:“它们都在相同的数量级内” ...我怀疑许多避免例外的人会期望它们的速度是原来的10倍。
加勒特·布鲁马

使用python 2.7.5在我的Fedora上运行代码显示,当a = 1时,“ if”版本(0.08 usec / pass)比“ try / except”版本(0.11 usec / pass)要快。
duleshi 2014年

@duleshi有趣。我想知道这是否是x86 / x64的东西?还是不同的处理器扩展?
基本


18

这个问题是误导的。如果您假设从未触发该异常,那么这两个都不是最佳代码。

如果您假设异常是作为错误条件的一部分而触发的,那么您已经超出了想要最佳代码的范围(而且您可能始终无法像这样细粒度地对其进行处理)。

如果您将异常用作标准控制流程的一部分(这是Pythonic的“询问宽恕,而不是允许”的方式),那么异常将被触发,代价取决于异常的种类,如果,以及您估计发生异常的时间百分比。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.