概述
timeit类
timeit.Timer
timeit.Timer.timeit方法
语法:timeit.Timer(str_1 , str_2).timeit(intvalue)
参数说明:
str_1 :字符串类型,为传入需要计时的语句或者函数,即:“执行语句"或"函数名()”
str_2:字符串类型,为传入第一个参数语句构建环境的导入语句。此时 timeit 构建起一个独立的虚拟环境, 手工地执行建立语句,然后手工地编译和执行被计时语句。即:"from main import 函数名"
intvalue:整型,为测试过程中被计时语句或函数执行的次数,默认为一百万次;返回所耗费的秒数
# timeit.Timer类计时
import timeit
def fun_1():
sum = 0
for i in range(10000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(100000):
sum += i
return sum
# 1、timeit.Timer.timeit()计时
# 使用timeit.Timer.timeit()计时,执行fun_1函数10000次,返回结果为秒
time_1 = timeit.Timer("fun_1()" , "from __main__ import fun_1").timeit(10000)
print("timeit.Timer.timeit()计时fun_1:" , time_1)
time_2 = timeit.Timer("fun_2()" , "from __main__ import fun_2").timeit(1000)
print("timeit.Timer.timeit()计时fun_2:" , time_2)
timeit.Timer.timeit()计时fun_1: 5.977923
timeit.Timer.timeit()计时fun_2: 6.3918026999999995
timeit.Timer.repeat方法
语法:timeit.Timer(str_1 , str_2).repect(intvalue_1 , intvalue_2)
参数说明:
str_1 :字符串类型,为传入需要计时的语句或者函数,即:“执行语句"或"函数名()”
str_2:字符串类型,为传入第一个参数语句构建环境的导入语句。此时 timeit 构建起一个独立的虚拟环境, 手工地执行建立语句,然后手工地编译和执行被计时语句。即:"from main import 函数名"
intvalue_1:整型,整个测试重复的次数,默认为3
intvalue_2:整型,为测试过程中被计时语句或函数执行的次数,默认为一百万次;repeat() 方法返回以秒记录的每个测试循环的耗时列表。Python 中的 max、min 函数可以把输入的列表返回成最大、最小值,如: min(timeit.Timer(str_1 , str_2).repeat(3, 1000000))
# timeit.Timer类计时
import timeit
def fun_1():
sum = 0
for i in range(10000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(100000):
sum += i
return sum
# 2、timeit.Timer.repect()计时
time_3 = timeit.Timer( "fun_1()" , "from __main__ import fun_1" ).repeat(3 , 10000)
print("timeit.Timer.repect()计时fun_1:" , time_3 , "max:" , max(time_3) , "mix:" , min(time_3))
timeit.Timer.repect()计时fun_1: [6.379943000000001, 5.9786114999999995, 6.348257100000001] max: 6.379943000000001 mix: 5.9786114999999995
timeit.timeit
timeit模块源码为:
def timeit(stmt="pass", setup="pass", timer=default_timer,
number=default_number):
"""Convenience function to create Timer object and call timeit method."""
return Timer(stmt, setup, timer).timeit(number)
def repeat(stmt="pass", setup="pass", timer=default_timer,
repeat=default_repeat, number=default_number):
"""Convenience function to create Timer object and call repeat method."""
return Timer(stmt, setup, timer).repeat(repeat, number)
参数说明:
stmt:这个参数就是statement,即需要计时的语句或者函数,可以直接接受字符串的表达式,也可以接受单个变量,还可以接受函数;
setup: 这个参数可以传入第一个参数语句构建环境的导入语句;
timer:这个参数一般使用不到,默认可不填;
timeit 类下面也有 repeat 和 timeit 方法,使用方法为 timeit.timeit 和 timeit.repeat
timeit.timeit方法
语法:timeit.timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number)
参数说明:
stmt:statement,即需要计时的语句或者函数,可以直接接受字符串的表达式,也可以接受单个变量,还可以接受函数;
setup: 这个参数可以传入第一个参数语句构建环境的导入语句;
timer:这个参数一般使用不到,默认可不填;
number:整型,为测试过程中被计时语句或函数执行的次数,默认为一百万次;返回所耗费的秒数
# timeit.timeit类
import timeit
def fun_1():
sum = 0
for i in range(10000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(100000):
sum += i
return sum
# 1、timeit.timeit()计时
# 使用timeit.timeit()计时,执行fun_1函数10000次,返回结果为秒
time_1 = timeit.timeit(stmt = "fun_1()" , setup="from __main__ import fun_1" , number=10000)
print("timeit.timeit()计时fun_1:" , time_1)
time_2 = timeit.timeit(stmt = "fun_2()" , setup="from __main__ import fun_2" , number=1000)
print("timeit.timeit()计时fun_2:" , time_2)
timeit.timeit()计时fun_1: 5.9416145
timeit.timeit()计时fun_2: 6.0575809
timeit.repect方法
语法:repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number)
参数说明:
stmt:statement,即需要计时的语句或者函数,可以直接接受字符串的表达式,也可以接受单个变量,还可以接受函数;
setup: 这个参数可以传入第一个参数语句构建环境的导入语句;
timer:这个参数一般使用不到,默认可不填;
number:整型,为测试过程中被计时语句或函数执行的次数,默认为一百万次;返回所耗费的秒数
repeat:整型,整个测试重复的次数,默认为3
# timeit.timeit类
import timeit
def fun_1():
sum = 0
for i in range(10000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(100000):
sum += i
return sum
# 2、timeit.repect()计时
time_3 = timeit.repeat(stmt= "fun_1()" , setup="from __main__ import fun_1" , repeat=10 , number=10000)
print("timeit.repect()计时fun_1:" , time_3 , "max:" , max(time_3) , "mix:" , min(time_3))
time_4 = timeit.repeat(stmt= "fun_2()" , setup="from __main__ import fun_2" , repeat=10 , number=1000)
print("timeit.repect()计时fun_2:" , time_4 , "max:" , max(time_4) , "mix:" , min(time_4))
timeit.timeit()计时fun_1: 6.05385
timeit.timeit()计时fun_2: 5.9594193
timeit.repect()计时fun_1: [6.1215308, 6.3348572999999995, 5.926046899999999] max: 6.3348572999999995 mix: 5.926046899999999
timeit.repect()计时fun_2: [6.573079199999999, 5.946404199999996, 6.233260800000004] max: 6.573079199999999 mix: 5.946404199999996
Profile类
日常工作会遇到相同功能,使用不同的实现方式,代码执行效率不同问题,代码优化的前提是需要了解性能瓶颈在什么地方,程序运行的主要时间是消耗在哪里,python 内置了丰富的性能分析工具,如 profile、cProfile和hotshot 等。其中 Profiler 是 python 自带的性能分析工具,能够描述程序运行时的性能,并提供各种统计帮助用户定位程序的性能瓶颈。
Python 标准模块提供了三种 profilers,分别为:cProfile、profile和hotshot
profile 的使用较为简单,只需要在使用之前进行 import 即可,也可以在命令行中使用
1、profile类分析python代码
# 使用profile类分析代码性能
import profile
def fun_1():
sum = 0
for i in range(10000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(10000):
sum += fun_1() # fun_2()调用fun_1()
return sum
def fun_3():
sum = 0
for i in range(10000):
sum += fun_2() # fun_3()调用fun_2()
return sum
if __name__ == "__main__":
profile.run("fun_1()")
profile.run("fun_2()")
profile.run("fun_3()")
profile.run("fun_1()" , "fun_1_result.txt" , "utf-8")
profile.run("fun_2()" , "fun_2_result.txt" , "utf-8")
profile.run("fun_3()" , "fun_3_result.txt" , "utf-8")
5 function calls in 0.016 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 :0(exec)
1 0.016 0.016 0.016 0.016 :0(setprofile)
1 0.000 0.000 0.000 0.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 ZX_03_Profile.py:5(fun_1)
1 0.000 0.000 0.016 0.016 profile:0(fun_1())
0 0.000 0.000 profile:0(profiler)
1005 function calls in 0.047 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.047 0.047 :0(exec)
1 0.000 0.000 0.000 0.000 :0(setprofile)
1 0.000 0.000 0.047 0.047 <string>:1(<module>)
1 0.000 0.000 0.047 0.047 ZX_03_Profile.py:11(fun_2)
1000 0.047 0.000 0.047 0.000 ZX_03_Profile.py:5(fun_1)
1 0.000 0.000 0.047 0.047 profile:0(fun_2())
0 0.000 0.000 profile:0(profiler)
1001005 function calls in 59.000 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 59.000 59.000 :0(exec)
1 0.000 0.000 0.000 0.000 :0(setprofile)
1 0.000 0.000 59.000 59.000 <string>:1(<module>)
1000 1.328 0.001 59.000 0.059 ZX_03_Profile.py:11(fun_2)
1 0.000 0.000 59.000 59.000 ZX_03_Profile.py:17(fun_3)
1000000 57.672 0.000 57.672 0.000 ZX_03_Profile.py:5(fun_1)
1 0.000 0.000 59.000 59.000 profile:0(fun_3())
0 0.000 0.000 profile:0(profiler)
参数说明:
ncalls:函数调用的次数
tottime:函数的总的运行时间,除掉函数中调用子函数的运行时间
percall:(第一个 percall)等于tottime / ncalls
cumtime:函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间
percall:(第二个 percall)即函数运行一次的平均时间,等于 cumtime / ncalls
filename:lineno(function):每个函数调用的具体信息
2、命令行分析python代码
test.py中代码如下:
# 使用命令行分析代码性能
import os
def fun_1():
sum = 0
for i in range(1000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(1000):
sum += fun_1() # fun_2()调用fun_1()
return sum
def fun_3():
sum = 0
for i in range(1000):
sum += fun_2() # fun_3()调用fun_2()
return sum
print(fun_1())
print(fun_2())
print(fun_3())
1、运行命令查看性能分析结果:
python -m cProfile test.py
2、性能分析结果保存到result文件:
python -m cProfile -o result test.py
3、使用pstats来格式化显示结果:
python -c “import pstats; p=pstats.Stats('reslut); p.print_stats()”
python -c "import pstats; p=pstats.Stats(‘result’); p.sort_stats(‘time’).print_stats()
其中sort_stats支持如下参数:
calls、cumulative、file、line、module、name、nfl、pcalls、stdname、time
Pstats类
使用pstats类分析性能步骤:
1、使用profile.run()将分析结果保存至某个文件内
profile.run(“函数名()” , “xxx.txt”)
2、创建Stats对象
variable = pstats.Stats(“xxx.txt”)
3、使用pstats格式化输出分析结果
strip_dirs(): 去掉无关的路径信息
sort_stats(): 排序,支持的方式和上述的一致,即:calls、cumulative、file、line、module、name、nfl、pcalls、stdname、time
print_stats(): 打印分析结果,可以指定打印前几行
按照函数名排序,只打印前3行函数的信息,参数还可为小数,表示前百分之几的函数信息
p.strip_dirs().sort_stats(“name”).print_stats(3)
按照运行时间和函数名进行排序
p.strip_dirs().sort_stats(“cumulative”, “name”).print_stats(0.8)
如果想知道有哪些函数调用了bar
p.print_callers(“bar”)
查看test()函数中调用了哪些函数
p.print_callees(“foo”)
# 使用pstats库分析性能
import pstats , profile
def fun_1():
sum = 0
for i in range(1000):
sum += i
return sum
def fun_2():
sum = 0
for i in range(1000):
sum += fun_1()
return sum
def fun_3():
sum = 0
for i in range(1000):
sum += fun_2()
return sum
if __name__ == "__main__":
# 将结果保存到result文件中
profile.run("fun_3()" , "fun_1_pstats_result.txt")
"""
使用 pstats 模块的代码
"""
# 创建Stats对象
p = pstats.Stats("fun_1_pstats_result.txt")
# strip_dirs(): 去掉无关的路径信息
# sort_stats(): 排序,支持的方式和上述的一致,
# 即:calls、cumulative、file、line、module、name、nfl、pcalls、stdname、time
# print_stats(): 打印分析结果,可以指定打印前几行
# 按照函数名排序,只打印前3行函数的信息
p.strip_dirs().sort_stats("name").print_stats(3)
# 按照运行时间和函数名进行排序
p.strip_dirs().sort_stats("cumulative", "name").print_stats(0.8)
# 哪些函数调用了fun_1
p.print_callers("fun_1")
# 查看fun_3()函数中调用了哪些函数
p.print_callees("fun_3")
Mon Jun 15 23:11:14 2020 fun_1_pstats_result.txt
1001005 function calls in 56.203 seconds
Ordered by: function name
List reduced from 8 to 3 due to restriction <3>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 56.203 56.203 <string>:1(<module>)
1 0.000 0.000 56.203 56.203 :0(exec)
1000000 54.984 0.000 54.984 0.000 ZX_05_Profile_pstats库.py:5(fun_1)
Mon Jun 15 23:11:14 2020 fun_1_pstats_result.txt
1001005 function calls in 56.203 seconds
Ordered by: cumulative time, function name
List reduced from 8 to 6 due to restriction <0.8>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 56.203 56.203 <string>:1(<module>)
1 0.000 0.000 56.203 56.203 :0(exec)
1000 1.219 0.001 56.203 0.056 ZX_05_Profile_pstats库.py:11(fun_2)
1 0.000 0.000 56.203 56.203 ZX_05_Profile_pstats库.py:17(fun_3)
1 0.000 0.000 56.203 56.203 profile:0(fun_3())
1000000 54.984 0.000 54.984 0.000 ZX_05_Profile_pstats库.py:5(fun_1)
Ordered by: cumulative time, function name
List reduced from 8 to 1 due to restriction <'fun_1'>
Function was called by...
ZX_05_Profile_pstats库.py:5(fun_1) <- ZX_05_Profile_pstats库.py:11(fun_2)(1000000) 56.203
Ordered by: cumulative time, function name
List reduced from 8 to 2 due to restriction <'fun_3'>
Function called...
ZX_05_Profile_pstats库.py:17(fun_3) -> ZX_05_Profile_pstats库.py:11(fun_2)(1000) 56.203
profile:0(fun_3()) -> :0(exec)(1) 56.203
:0(setprofile)(1) 0.000