想在python中查看每一行代码运行的时间?试试line_profiler吧!
在日常使用python中,新手由于经验不足总是会写下一些不成熟的代码,这些代码虽然能运行,但是却可能是非常消耗时间或CPU成本的,所以这时候一个能计算每行代码运行时间的工具就显得很有用了。本文要介绍的line_profiler就是这样的一个工具哦,快快使用起来吧!
对于我这种学艺不精的渣渣来说,写出运行耗时较多的代码是很经常出现的(尴尬,嘿嘿嘿!)。前不久就在自己之前使用的代码上栽了跟头,师兄的代码只用了一到两分钟,而我的用了十多分钟,虽说他用的是perl,但我在想python不可能就是真的这么慢吧。最后想着还是看下是不是自己的代码确实很烂,我就尝试寻找能计算每行代码运行时间的包,最终还真的找到了,就是要介绍的line_profiler啦。其它工具可能也有,例如Heartrate等等,但感觉用起来没有line_profiler方便,我也就没用啦。最终也发现确实是自己的代码写的菜!!!经过一番修改之后速度快了好多倍。。。
当然这种模块呢,我们一般就是在测试时用一下,所以能够到达基本使用的地步我觉得就足够啦,所以本文就仅仅教大家怎么去简单的使用就OK啦!还有就是profile在这里可以理解成性能剖析的意思哦!
文章目录
安装line_profiler
安装直接使用 pip install line_profiler 命令即可,但是我在我的win10电脑上使用这个命令是会报错的,报错非常长的一串,部分截图如下:
开始报错的地方写着 Building wheel for line-profiler (PEP 517) … error,这个错我也在网上搜索了很久,最终还是没有解决,按照某个博主的教学安装Cpython也不行。最后在某篇文章还是回答中看到了可以使用anaconda的conda install试试,最后我也只有妥协重新装上anaconda再配置好python环境等等环境变量,最后再使用conda install line_profiler就没问题啦。
这是我个人的粗劣的解决方式,读者若有好方法也可以提出来呀!
但是也不一定大家都会碰上这个问题哦,我在linux服务器上就可以直接使用pip安装的哦。没有问题就可以不用管啦!
使用方式1(使用profile装饰器)
要注意line_profiler只能计算函数中代码的运行时间哦,所以要计算时间的话就先把代码转换到函数中吧。使用line_profiler大致有两种方式,即:
- 在命令行调用包作者的脚本kernprof来运行你的py文件
- 在脚本中写上使用line_profiler的方式。
这两种方法都可以,看哪个合适就用哪个吧!
由于连接网络可能会多花些时间,看起来效果会更好。就用简单的爬虫来举例啦!简单的爬虫的知识大家可以参考我之前写的文章哦!在这里
话不多说,先看方式1:
# 脚本名为test.py
import requests
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'}
# 加的一个请求头,这样就可以简单的伪装成浏览器啦
# 使用line_profiler的第一种方式需要加上这个profile装饰器,在编辑器中由于有拼写检查,
# 这个地方可能会报错,但是不用管啦,反正我们是在命令行运行脚本的,kernprof会自动帮我们处理的。
@profile
def get_url_txt(url_list):
f = open('text.txt','w',encoding='utf-8')
for url in url_list:
text = requests.get(url, headers=headers).text
f.write(text)
return 'finished'
url_list = ['http://www.baidu.com', 'http://www.taobao.com',\
'https://blog.csdn.net/keepaware/article/details/111655393']
# 传入一个要爬取的网址列表
result = get_url_txt(url_list)
# 调用函数
print(result)
# 查看返回值
这段代码,我在我的windows命令行将当前目录切换到脚本存放位置后,使用 kernprof -l -v test.py即可开始运行代码(-l 代表逐行分析,-v代表将结果打印出来),运行的结果如下:
# 复制过来的是文本,我直接在上面注释一下哈
finished
Wrote profile results to rg.py.lprof
Timer unit: 1e-07 s
# 这应该是计时的单位
Total time: 1.81267 s
# 总共花去的时间
File: test.py
Function: get_url_txt at line 7
# 计时的函数
Line # Hits Time Per Hit % Time Line Contents
==============================================================
7 @profile
8 def get_url_txt(url_list):
9 1 44804.0 44804.0 0.2 f = open('text.txt','w',encoding='utf-8')
10 4 75.0 18.8 0.0 for url in url_list:
11 3 18061366.0 6020455.3 99.6 text = requests.get(url, headers=headers).text
12 3 20404.0 6801.3 0.1 f.write(text)
13 1 3.0 3.0 0.0 return 'finished'
# 上面这一段就是运行代码的时间结果啦,hits即某行代码运行了几次,
# time应该就是使用的时间,这里需要乘以上面的时间单位才是真正用掉的时间,
# 所以可以看到最久时间的11行都只花了18061366 * 1e-07 s哦。
# 后面per hit就是每次运行某行代码所花的时间,% Time 就是占据整个
# 代码运行时间的百分比呗。还是很好理解的,是吧!
使用方式2(直接在脚本中调用LineProfiler)
import requests
import line_profiler as lp
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'}
# 这种方式就不用加profile装饰器啦
def get_url_txt(url_list):
f = open('text.txt','w',encoding='utf-8')
for url in url_list:
text = requests.get(url, headers=headers).text
f.write(text)
return 'finished'
url_list = ['http://www.baidu.com', 'http://www.taobao.com',
'https://blog.csdn.net/keepaware/article/details/111655393']
profile = lp.LineProfiler(get_url_txt)
# 自己制作一个profile工具,并且传入要分析的代码
profile.enable()
# 起始分析
get_url_txt(url_list)
# 调用函数,这里还是正常传入参数的哦
profile.disable()
# 停止分析,这里就相当于只分析get_url_txt这个函数
profile.print_stats()
# 打印结果
运行的结果同上,不展示咯!
使用方式3(直接在脚本中调用LineProfiler)
import requests
from line_profiler import LineProfiler
# 只需要导入LineProfiler即可
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'}
def get_url_txt(url_list):
f = open('text.txt','w',encoding='utf-8')
for url in url_list:
text = requests.get(url, headers=headers).text
f.write(text)
return 'finished'
url_list = ['http://www.baidu.com', 'http://www.taobao.com',
'https://blog.csdn.net/keepaware/article/details/111655393']
lp = LineProfiler()
# 使用LineProfiler来分析
profile = lp(get_url_txt)
# 这里还可以使用profile.add_function()来添加你想要额外计算的函数哦,就不再介绍了,我也还没用过。
# 同样制作profile
profile(url_list)
# 但这里传入给profile的是参数,替代了上面向函数传入的方式
lp.print_stats()
# 打印结果
运行结果也同上哦,这里就不再展示了。
产生的结果文件
细心的你可能会发现运行这个工具会产生一个文件,后缀是.py.lprof,我这里全名也就是test.py.lprof。这个文件也是有记录你代码运行时间的结果的哦,所以你也可以查看这个文件来回顾之前的时间记录。
使用方式为:
python -m line_profiler test.py.lprof
# 这样就能看到和刚刚你看到的结果一样的结果啦。
# 这里python -m代表的是将后面模块当做脚本来运行,line_profiler是我们安装的模块嘛!这样还不需要
# 我们去寻找这个脚模块的绝对路径的哈,所以还是比较方便的。
# -m具体我也还没搞懂,后面会再了解一下
叮
个人觉得这个工具还是挺好用的,用来查看某些代码花去的时间,来适当修改自己的代码。网上教程也挺多的,但是好像有点乱,所以就整理了一下,希望能帮上有需要的人哦!
刚刚看到其实除了line_profiler外还有一个memory_profiler,是用来计算每行代码消耗内存量的工具,使用方式好像和line_profiler差不多,大家有兴趣也可以了解一下哦,不过实际上现在电脑的内存都还是较大,一般情况下还是不太需要用来测试内存使用量的。
参考:line_profiler 逐行分析
参考:How do I use line_profiler (from Robert Kern)?
参考:https://github.com/rkern/line_profiler
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)