Python异常对代码运行性能的影响实例解析


Posted in Python onFebruary 08, 2018

前言

Python的异常处理能力非常强大,但是用不好也会带来负面的影响。我平时写程序的过程中也喜欢使用异常,虽然采取防御性的方式编码会更好,但是交给异常处理会起到偷懒作用。偶尔会想想异常处理会对性能造成多大的影响,于是今天就试着测试了一下。

Python异常(谷歌开源风格指南)

tip:

允许使用异常, 但必须小心。

定义:

异常是一种跳出代码块的正常控制流来处理错误或者其它异常条件的方式。

优点:

正常操作代码的控制流不会和错误处理代码混在一起. 当某种条件发生时, 它也允许控制流跳过多个框架. 例如, 一步跳出N个嵌套的函数, 而不必继续执行错误的代码。

缺点:

可能会导致让人困惑的控制流. 调用库时容易错过错误情况。

结论:

异常必须遵守特定条件:

像这样触发异常: raise MyException("Error message") 或者 raise MyException . 不要使用两个参数的形式( raise MyException, "Error message" )或者过时的字符串异常( raise "Error message" )。
模块或包应该定义自己的特定域的异常基类, 这个基类应该从内建的Exception类继承. 模块的异常基类应该叫做”Error”。

class Error(Exception):
  pass

永远不要使用 except: 语句来捕获所有异常, 也不要捕获 Exception 或者 StandardError , 除非你打算重新触发该异常, 或者你已经在当前线程的最外层(记得还是要打印一条错误消息). 在异常这方面, Python非常宽容, except: 真的会捕获包括Python语法错误在内的任何错误. 使用 except: 很容易隐藏真正的bug。

尽量减少try/except块中的代码量. try块的体积越大, 期望之外的异常就越容易被触发. 这种情况下, try/except块将隐藏真正的错误。

使用finally子句来执行那些无论try块中有没有异常都应该被执行的代码. 这对于清理资源常常很有用, 例如关闭文件。
当捕获异常时, 使用 as 而不要用逗号. 例如

try:
  raise Error
except Error as error:
  pass

设计实验方式

采取比较简单直观的对照实验。

先定义一个装饰器,用来计算每个函数执行所需时间:

def timer(func):
  import time
  def wrapper(*args, **kwargs):
    startTime = time.time()
    f = func(*args, **kwargs)
    endTime = time.time()
    passTime = endTime - startTime
    print "执行函数%s使用了%f秒" % (getattr(func, "__name__"), passTime)
    return f
  return wrapper

然后用该装饰器装饰测试的函数即可。

再定义一个叫do_something的函数,这个函数中就做一件事,把1赋值给变量a。在每个测试函数中,都会调用这个函数1000000次。

do_something:

def do_something():
  a = 1

我根据情况设计了不同的测试组:

测试组1(直接执行耗时操作):

@timer
def test1():
  for _ in xrange(1000000):
    do_something()

测试组2(耗时操作放在try中执行,不抛出错误):

@timer
def test2():
  try:
    for _ in xrange(1000000):
      do_something()
  except Exception:
    do_something()
  else:
    pass
  finally:
    pass

测试组3(try放耗时操作中,try每一次操作,不抛出错误):

@timer
def test3():
  for _ in xrange(1000000):
    try:
      do_something()
    except Exception:
      do_something()
    else:
      pass
    finally:
      pass

测试组4(try放耗时操作中,try每一次操作并进行异常处理(捕捉抛出的特定异常)):

@timer
def test4():
  zero = 0
  for _ in xrange(1000000):
    try:
      if zero == 0:
        raise ZeroDivisionError
    except ZeroDivisionError:
      do_something()
    else:
      pass
    finally:
      pass

测试组5(try放耗时操作中,try每一次操作并进行异常处理(捕捉所有异常 try…except BaseException)):

@timer
def test5():
  zero = 0
  for _ in xrange(1000000):
    try:
      if zero == 0:
        raise ZeroDivisionError
    except BaseException:
      do_something()
    else:
      pass
    finally:
      pass

测试组6(try放耗时操作中,try每一次操作并进行异常处理(捕捉所有异常 不带任何异常类型)):

@timer
def test6():
  zero = 0
  for _ in xrange(1000000):
    try:
      if zero == 0:
        raise ZeroDivisionError
    except:
      do_something()
    else:
      pass
    finally:
      pass

测试组7(耗时操作放在except中):

@timer
def test7():
  zero = 0
  try:
    if zero == 0:
      raise ZeroDivisionError
  except ZeroDivisionError:
    for _ in xrange(1000000):
      do_something()
  else:
    pass
  finally:
    pass

测试组8(防御式编码):

@timer
def test8():
  zero = 0
  for _ in xrange(1000000):
    if zero == 0:
      do_something()

执行结果

Python异常对代码运行性能的影响实例解析

对比结论

  • 通过对比1和2,可以得知直接执行耗时操作和耗时操作放在try中执行并无异常触发时性能消耗几乎是一样的。
  • 通过对比2和7,可以得知使用异常的使用无论是把代码放在 try 中执行还是在 except 中执行性能消耗几乎是一样的。
  • 通过对比2和3,可以得知当不抛出错误时,把try放耗时操作中比耗时操作放在try中性能消耗要略大。
  • 通过对比3和4,可以得知当使用try时无异常抛出跟使用try时抛出异常性能消耗几乎相差好几倍。
  • 通过对比4和5,可以得知try放耗时操作中时,try每一次操作并进行异常处理(捕捉抛出的特定异常)跟try每一次操作并进行异常处理(捕捉所有异常 try…except BaseException)性能消耗几乎是一样的。
  • 通过对比4和8,可以得知使用防御性方式编码比捕捉异常方式性能消耗几乎相差好几倍。
  • 通过对比5和6,可以得知捕捉所有异常(try…except)方式比捕捉所有异常(try…except BaseException)方式要略快。

总结

  1. 由以上对比结论,可以总结为:
  2. 无论是把代码放在 try 中执行还是在 except 中执行性能消耗几乎是一样的。
  3. 直接执行代码与放在try中执行且不抛出异常时性能消耗几乎是一样的,当然理论上try会消耗一点性能,可以忽略不计。
  4. 虽然try…except的方式比try…except BaseException和捕捉抛出的特定异常的方式要略快,但扔不建议采取这种方式,因为前者很容易隐藏真正的bug,从而带来严重后果。
  5. 通常要采取捕捉抛出的特定异常而不是捕捉所有异常,虽然二者性能消耗几乎一样。
  6. 防御性方式编码比捕捉异常方式性能消耗几乎相差好几倍,应尽量采取这种编程方式,提升性能并且更靠谱。

以上就是本文关于Python异常对代码运行性能的影响实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
pycharm 使用心得(三)Hello world!
Jun 05 Python
Pycharm学习教程(7)虚拟机VM的配置教程
May 04 Python
Python matplotlib画图实例之绘制拥有彩条的图表
Dec 28 Python
python编程测试电脑开启最大线程数实例代码
Feb 09 Python
python如何定义带参数的装饰器
Mar 20 Python
Python3.4学习笔记之列表、数组操作示例
Mar 01 Python
python3的url编码和解码,自定义gbk、utf-8的例子
Aug 22 Python
Python函数的定义方式与函数参数问题实例分析
Dec 26 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
Mar 11 Python
利用pyecharts读取csv并进行数据统计可视化的实现
Apr 17 Python
Python操作PostgreSql数据库的方法(基本的增删改查)
Dec 29 Python
详解pandas映射与数据转换
Jan 22 Python
Python科学计算包numpy用法实例详解
Feb 08 #Python
Python多进程并发与多线程并发编程实例总结
Feb 08 #Python
Python的CGIHTTPServer交互实现详解
Feb 08 #Python
Python获取CPU、内存使用率以及网络使用状态代码
Feb 08 #Python
python实现二叉查找树实例代码
Feb 08 #Python
单链表反转python实现代码示例
Feb 08 #Python
Python测试人员需要掌握的知识
Feb 08 #Python
You might like
PHP 文件扩展名 获取函数
2009/06/03 PHP
PHP中把数据库查询结果输出为json格式简单实例
2015/04/09 PHP
PHP的Laravel框架中使用AdminLTE模板来编写网站后台界面
2016/03/21 PHP
laravel5创建service provider和facade的方法详解
2016/07/26 PHP
PHP实现带重试功能的curl连接示例
2016/07/28 PHP
Yii2中hasOne、hasMany及多对多关联查询的用法详解
2017/02/15 PHP
PHP实现的ID混淆算法类与用法示例
2018/08/10 PHP
jQuery 表单验证扩展代码(一)
2010/10/11 Javascript
Js 导出table内容到Excel的简单实例
2013/11/19 Javascript
JavaScript实现添加及删除事件的方法小结
2015/08/04 Javascript
使用PHP+JavaScript将HTML页面转换为图片的实例分享
2016/04/18 Javascript
JavaScript中的子窗口与父窗口的互相调用问题
2017/02/08 Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
2017/05/19 Javascript
CentOS 安装NodeJS V8.0.0的方法
2017/06/15 NodeJs
Angular 2父子组件数据传递之局部变量获取子组件其他成员
2017/07/04 Javascript
angular4中引入echarts的方法示例
2019/01/29 Javascript
JavaScript数组去重的方法总结【12种方法,号称史上最全】
2019/02/28 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
2019/05/10 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
2分钟实现一个Vue实时直播系统的示例代码
2020/06/05 Javascript
[01:35]辉夜杯战队访谈宣传片—LGD
2015/12/25 DOTA
Django中间件实现拦截器的方法
2018/06/01 Python
pandas.read_csv参数详解(小结)
2019/06/21 Python
Python实现非正太分布的异常值检测方式
2019/12/09 Python
python dataframe NaN处理方式
2019/12/26 Python
pycharm运行程序时看不到任何结果显示的解决
2020/02/21 Python
如何使用Cython对python代码进行加密
2020/07/08 Python
详解CSS3 rem(设置字体大小) 教程
2017/11/21 HTML / CSS
德国古洛迷亚百货官网:GALERIA Kaufhof
2017/06/20 全球购物
介绍一下linux文件系统分配策略
2012/11/17 面试题
酒店管理自荐信
2013/10/23 职场文书
安全生产目标管理责任书
2014/07/25 职场文书
离婚协议书范文2014
2014/10/16 职场文书
英语导游词
2015/02/13 职场文书
2015圣诞节贺卡寄语
2015/03/24 职场文书
成本低的5个创业项目:投资小、赚钱快
2019/08/20 职场文书