Python调优
一直给大家分享机器学习呀、算法呀、数学呀等等的,其实工程的东西说的比较少,本文介绍Python的性能优化,再好的算法也需要优雅的调优将来才能走的更远,对于算法来说Python几乎是天天不离手,所以对于Python的理解必须要强过其他人,否则你怎么保证你的程序是最好呢?
cProfile
首先我们来认识一个工具,你如果没有做过Python调优你肯定没有用过,cProfile是一个可以发现你程序性能的工具,接下来我们就来学习这个工具的用法。
1.模块 profile:这个模块是完全使用 Python编写的,给程序执行增加了很大的开销 。 这 个模块之所以出现在标准库中,原因在于其强大的平台支持和易于扩展 。
2.模块 cProfile:这是主要的剖析模块,其接口与 profile 相同 。 这个模块是使用 C语言编写的,因此开销很小,适合用作通用剖析器。
首先我们来看一个例子:
import time
def add_1():
time.sleep(0.2)
return 1
def add_2():
return 2
sum_num = 0
for i in range(100):
sum_num += add_1()
sum_num += add_2()
if sum_num >= 100:
print "success"
break
代码十分简单,就是不同就是,add_1函数有一个sleep的操作,其实是想体现出性能问题,接下来这段代码的输出是怎么样的呢?如下就是运行这段代码性能分析的命令。
python -m cProfile effect.py
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 6.878 6.878 effect.py:1(<module>)
34 0.000 0.000 6.877 0.202 effect.py:4(add_1)
34 0.000 0.000 0.000 0.000 effect.py:9(add_2)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
34 6.876 0.202 6.876 0.202 {time.sleep}
可以看出,上面的命令输出了如下的几列指标,那么我们来解释这些指标分别代表什么意思?
ncalls:函数被调用的次数。
tottime: 执行函数花费的总时间,不考虑其他函数调用 。
cumtime: 执行函数花费的总时间 ,考虑其他函数调用 。
percall: 单次函数调用花费的时间一一可通过将总时间除以调用次数得到。
filename:lineno:文件名和相应的行号。 调用 C语言扩展模块时,不包含这种信息
是不是非常清晰,time.sleep这行代码花费了大部分的时间,那么我们做当个python脚本的分析的时候也能发现我们代码中的一些问题,当然还有其他的方式可以实现,例如你可以使用计算时间的方式发现每行代码的执行时间,就是实现可能会比较繁琐。
你可能还有另外一个问题,那就是我的程序中可以调用类似这样的代码吗,我不想在程序的最外层执行这样的shell命令。
import cProfile
def add_1():
time.sleep(0.2)
return 1
cProfile.run("add_1()")
通过这样的方式能够测试一个函数的性能报告。
Cython
Cython是一种扩展 Python 的语言,这是通过支持给函数、变量和类声明类型来实现的 。 这 些类型声明让 Cython能够将 Python脚本编译成高效的 C语言代码 。Cython还可充 当 Python 和 C 语言之间的桥梁,因为它提供了易于使用的结构,让你能够编写到外部 C和 C++例程的接口。
Cython语法被设计成 Python语法的超集 。 在不做任何修改的情况下, Cython 就能够编译大 部分 Python模块( 例外的情况不多)。 Cython源代码文件的扩展名为.pyx,可使用命令 cython 编译成 C语言文件。
新建一个cpython.pyx
def hello():
print "hello"
简单的不要不要的,下面我们来编一个这个文件。
cython hello .pyx
这个时候会产生另一文件,cpython.c。
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -lm -I venv/include/python2.7/ -o cpython.so cpython.c
以上这个过程,我们就将python源码变成了C代码,神奇吧,C的运行性能可是比python 块很多的。Cython的语法这里就不详细介绍了,希望大家了解以后能知道通过python能够编译生成C的代码从而提升性能的门路。
总结
本节介绍了一下python性能分析小工具,大家可以尝试,其实对于工具而言无非是知道和不知道的区别,了解就好,我们后面会介绍更多关于python优化的内容。