当前位置: 首页 > news >正文

python性能测试脚本_精通Python自动化脚本-第二章 Python脚本调试和性能测试

精通Python自动化脚本-运维人员宝典完整目录:

什么是调试?

调试(debugging)是一个解决代码中错误或导致软件不能正常运行的问题的过程。Python中的调试非常容易。Python调试器设置条件断点并对源码逐行调试。我们将使用Python标准库中的 pdb 模块来对我们的Python脚本进行调试。

Python 的调试技术

为更好的调试Python程序,可以使用不同的技术。我们就来看看Python调试的四种技术:print()语句:这是了解具体发生情况的最简单的方式,这样我们可以检查执行的内容

logging:这类似于print语句但带更多的上下文信息,因此我们可以更全面的了解情况

pdb调试器:这是最常使用的调试技术。使用 pdb 的优势是能够在命令行、解释器以及程序中使用 pdb

IDE调试器:IDE有内置的调试器。这让开发者可以执行自己的代码,然后开发者可以在程序执行过程中检查代码

错误处理(异常处理)

在这一部分中我们将学习Python如何处理异常。但首先什么是异常呢?异常是在程序执行过程中发生的错误。每当错误发生时,Python会生成一个异常,使用try…except代码块来进行处理。有时异常程序无法处理,因此会导致报错信息。下面我们就来看一些异常的示例:

在你的终端中,启动python3交互控制台,我们一起来看一些异常示例:

>>> 50 / 0

Traceback (most recent call last):

File "", line 1, in

ZeroDivisionError: division by zero

>>> 6 + abc*5

Traceback (most recent call last):

File "", line 1, in

NameError: name 'abc' is not defined

>>> 'abc' + 2

Traceback (most recent call last):

File "", line 1, in

TypeError: Can't convert 'int' object to str implicitly

>>> import abcd

Traceback (most recent call last):

File "", line 1, in

ImportError: No module named 'abcd'

这就是异常的一些示例。下面我们来看如何处理这些异常。

每当Python程序中发生错误时,就会抛出异常。我们也可使用raise关键字来强制抛出异常。

下来我们来看一个处理异常的try…except代码块。在try代码块中,我们将编写可能生成异常的代码。在except代码块中,我们将编写异常的处理方式。try…except的语法如下:

try:

statement(s)

except:

statement(s)

一个try代码块可带有多个except语句。我们可通过在except关键字之后输入异常的名称来处理指定的异常。处理指定异常的语法如下:

try:

statement(s)

except exception_name:

statement(s)

下面我们创建一个exception_example.py脚本来捕获ZeroDivisionError。在脚本中编写如下代码:

a = 35

b = 37

try:

c = a +b

print("The value of c is:", c)

d = b / 0

print("The value of d is:", d)

except:

print("Division by zero is not possible")

print("Out of try...except block")

像下面这样运行脚本,将会得到如下结果:

vagrant@python-scripting:~$ python3 exception_example.py

The value of c is: 72

Division by zero is not possible

Out of try...except block

调试器工具

Python中支持很多种调试工具:winpdb

pydev

pydb

pdb

gdb

pyDebug

这一部分中,我们将学习pdb Python调试器。pdb是Python标准库的一部分并一直可以直接使用。

pdb调试器

pdbs模块用于调试Python程序。Python程序使用pdb交互源代码调试器来调试程序。pdb设置断点交检查栈帧,列出源代码。

下面我们将学习如何使用pdb调试器。使用这一调试器有三种方式:在解释器之中

通过命令行

在Python脚本中

我们将创建一个pdb_example.py脚本并在该脚本中添加如下内容:

class Student:

def __init__(self, std):

self.count = std

def print_std(self):

for i in range(self.count):

print(i)

return

if __name__ == "__main__":

Student(5).print_std()

使用这一脚本作为学习Python调试的示例,我们将了解如何启动调试器的细节。

解释器内调试

要从Python交互控制台中启动调试器,我们使用run()或runeval()。

启动python3交互控制台。运行如下命令来启动控制台:

$ python3

导入我们的pdb_example脚本名和pdb模块。下面我们将使用run(),并且我们会传入一个字符串表达式来作为run()的参数,由Python解释器自身进行运行:

>>> import pdb_example

>>> import pdb

>>> pdb.run('pdb_example.Student(5).print_std()')

> (1)()

(Pdb)

要继续调试,在(Pdb)提示符之后输入continue并按下Enter。我果想要了解这里可以使用的选项,在(Pdb)提示符之后按下两次Tab键。

在输入continue之后,我们将得到如下的输出:

>>> import pdb_example

>>> import pdb

>>> pdb.run('pdb_example.Student(5).print_std()')

> (1)()

(Pdb) continue

0

1

2

3

4

>>>

命令行调试

运行调试器最简单也最直接的方式是通过命令行。我们的程序将作为调试器的输入。我们可以这样在命令行中使用调试器:

$ python3 -m pdb pdb_example.py

在从命令行运行调试器时,源代码会被载入并在调试器找到的第一行停止执行。输入continue来继续调试。输出如下:

vagrant@python-scripting:~$ python3 -m pdb pdb_example.py

> /home/vagrant/pdb_example.py(1)()

-> class Student:

(Pdb) continue

0

1

2

3

4

The program finished and will be restarted

> /home/vagrant/pdb_example.py(1)()

-> class Student:

(Pdb)

Python脚本内调试

以上两种技术会在Python程序开始时启动调试器。但第三种方法对于长期处理来说最佳。要在脚本中启动调试器,使用set_trace()。

现在修改pdb_example.py文件如下:

import pdb

class Student:

def __init__(self, std):

self.count = std

def print_std(self):

for i in range(self.count):

pdb.set_trace()

print(i)

return

if __name__ == "__main__":

Student(5).print_std()

现在运行程序如下:

vagrant@python-scripting:~$ python3 pdb_example.py

> /home/vagrant/pdb_example.py(10)print_std()

-> print(i)

(Pdb) continue

0

> /home/vagrant/pdb_example.py(9)print_std()

-> pdb.set_trace()

(Pdb)

set_trace()是一个Python函数,因此可以在程序的任意处调用它。所以我们有三种方式来启动调试器。

基本程序崩溃调试

在这一部分中,我们来看看trace模块。trace模块有助于追踪程序的执行。因此不论何时程序崩溃,我们都能了解在哪里出现的崩溃。我们可以在脚本中导入也可以通过命令行来使用trace模块。

现在我们将创建一个名为trace_example.py的脚本并在该脚本中编写如下代码:

class Student:

def __init__(self, std):

self.count = std

def go(self):

for i in range(self.count):

print(i)

return

if __name__ == "__main__":

Student(5).go()

输出如下:

vagrant@python-scripting:~$ python3 -m trace --trace trace_example.py

--- modulename: trace_example, funcname:

trace_example.py(1): class Student:

--- modulename: trace_example, funcname: Student

trace_example.py(1): class Student:

trace_example.py(2): def __init__(self, std):

trace_example.py(5): def go(self):

trace_example.py(10): if __name__ == "__main__":

trace_example.py(11): Student(5).go()

--- modulename: trace_example, funcname: __init__

trace_example.py(3): self.count = std

--- modulename: trace_example, funcname: go

trace_example.py(6): for i in range(self.count):

trace_example.py(7): print(i)

0

trace_example.py(6): for i in range(self.count):

trace_example.py(7): print(i)

1

trace_example.py(6): for i in range(self.count):

trace_example.py(7): print(i)

2

trace_example.py(6): for i in range(self.count):

trace_example.py(7): print(i)

3

trace_example.py(6): for i in range(self.count):

trace_example.py(7): print(i)

4

trace_example.py(6): for i in range(self.count):

trace_example.py(8): return

--- modulename: trace, funcname: _unsettrace

trace.py(77): sys.settrace(None)

因此通过在命令行中使用trace --trace,开发人员可以对程序逐行追踪。这样在程序崩溃时,开发人员就会知道发生崩溃的实例。

程序性能和时耗分析

对Python程序进行性能分析(profiling)表示度量程序的执行时间。它计量每个函数所花的时间。Python的cProfile模块用于对Python程序进行性能分析。

cProfile模块

正如前文所讲到的,性能分析表示度量程序的执行时间。我们就来使用cProfile Python模块对程序进行性能分析。

现在来编写一个cprof_example.py脚本并加入如下代码:

mul_value = 0

def mul_numbers(num1, num2):

mul_value = num1 * num2

print("Local Value:", mul_value)

return mul_value

mul_numbers(58, 77)

print("Global Value:", mul_value)

运行程序,将会看到如下的输出:

vagrant@python-scripting:~$ python3 -m cProfile cprof_example.py

Local Value: 4466

Global Value: 0

6 function calls in 0.001 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)

1 0.000 0.000 0.001 0.001 cprof_example.py:1()

1 0.000 0.000 0.000 0.000 cprof_example.py:2(mul_numbers)

1 0.000 0.000 0.001 0.001 {built-in method builtins.exec}

2 0.001 0.000 0.001 0.000 {built-in method builtins.print}

1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}

因此,使用cProfile,所有调用的函数都被打印,并包含各个函数所消耗的时间。下面我们来看看这些列头的含义:ncalls: 调用次数

tottime: 给定函数花费的总时间

percall: tottime除心ncalls所得的商

cumtime: 当前以及其子函数所花费的累计时间

percall: cumtime除以原始调用所得的商

filename:lineno(function): 提供函数各自的数据

timeit

timeit是一个Python模块,用于对Python脚本的各部分进行计时。我们可以在命令行中调用timeit,也可以在脚本中导入timeit模块。下面我们来编写一个脚本来对代码片断进行计时。创建一个timeit_example.py脚本并编写如下内容:

import timeit

prg_setup = "from math import sqrt"

prg_code = '''

def timeit_example():

list1 = []

for x in range(50):

list1.append(sqrt(x))

'''

# timeit 语句

print(timeit.timeit(setup = prg_setup, stmt = prg_code, number = 10000))

运行结果:

vagrant@python-scripting:~$ python3 timeit_example.py

0.0010215669999524835

使用timeit,,我们可以决定要对哪段代码进行性能的度量。因此,我们可以轻易地定义setup代码来作为我们想单独执行测试的代码片断。主代码默认运行100万次,但setup代码仅运行一次。

加速程序运行

有很多方式来让Python程序运行得更快,比如:对认定为瓶颈的代码进行性能分析

使用内置函数和库,这样解释器不用执行不同循环

避免使用全局变量,因为Python在访问全局变量时速度很慢

使用已有的包

总结

在本章中,我们学习了调试程序和性能分析的重要性。还学习用于调试的不同技术。我们学习了pdb Python调试器以及如何处理异常。还学习了如何使用Python中的cProfile和timeit模块来对脚本进行性能和时耗分析。最后我们学习了如何加速脚本的运行。

下一章中,我们将学习Python中的单元测试。我们会学习如何创建和使用单元测试。

课后问题要调用程序,使用哪个模块?

查看如何在ipython中使用所有的别名函数和魔法函数。

什么是全局解释器锁(Global interpreted lock (GIL))?

PYTHONSTARTUP, PYTHONCASEOK, PYTHONHOME和PYTHONSTARTUP环境变量的目的是什么?

以下代码的输出是什么?a) [0], b) [1], c) [1, 0], d) [0, 1]

def foo(k): k = [1] q = [0] foo(q) print(q)

以下哪个是无效变量?

a) my_string_1

b) 1st_string

c) foo

d) _

扩展阅读

相关文章:

  • python rindex_Python index和rindex方法
  • lcd图片转二进制工具_用完即走丨无需安装!900+工具在线使用,真正的NICE TOOL!...
  • fastjson jsonobject 转bean失败_漫谈FastJSON
  • vs 堆栈保留大小_亚冠杯:上海申花vs东京FC【绝密情报】
  • python文件名可以用中文吗_在文件名中可以使用“/”吗?
  • idea打开项目xml的路径飘红_从零开始搭建SpringBoot项目(小白版,踏遍万水千坑)...
  • docker 安装nginx_docker安装nginx镜像
  • 概率神经网络_深度学习算法(第33期)强化学习之神经网络策略学习平衡车
  • vasp 安装_安装Atomic Simulation Environment (ASE)
  • fastreport调用frf文件直接打印_不是我吹,20M的压缩文件我只用了1秒!
  • python属于哪类型的编程语言_python属于什么类型的语言
  • python excel接口测试_利用python和excel 搭建接口测试框架
  • sql 日期月转换到日_速来!9月新增雅思考点、考试日期(更新至8月16日)
  • python处理csv文件 pandas_Pandas操作CSV文件的读写实现方法
  • 组播应用场景_慧联应用研究 | 浅谈LoRaWAN组播技术和应用(市场篇)
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • JAVA_NIO系列——Channel和Buffer详解
  • ng6--错误信息小结(持续更新)
  • Python爬虫--- 1.3 BS4库的解析器
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • swift基础之_对象 实例方法 对象方法。
  • 利用DataURL技术在网页上显示图片
  • 前端自动化解决方案
  • #define、const、typedef的差别
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET gRPC 和RESTful简单对比
  • .NET Project Open Day(2011.11.13)
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • [ solr入门 ] - 利用solrJ进行检索
  • [ 数据结构 - C++] AVL树原理及实现
  • []新浪博客如何插入代码(其他博客应该也可以)
  • [APIO2012] 派遣 dispatching
  • [ARM]ldr 和 adr 伪指令的区别
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测
  • [codevs 2822] 爱在心中 【tarjan 算法】
  • [hdu 3065] 病毒侵袭持续中 [AC自动机] [病毒特征码匹配]
  • [Head First设计模式]策略模式
  • [idea]关于idea开发乱码的配置
  • [IDF]聪明的小羊
  • [IE9] GPU硬件加速到底是实用创新还是噱头
  • [iOS]-UIKit
  • [jQuery]使用jQuery.Validate进行客户端验证(中级篇-上)——不使用微软验证控件的理由...
  • [LeetCode]Multiply Strings
  • [Mac软件]Goldie App v2.2 Mac黄金比例设计工具