有時候我們很希望看到程序中某個函數(shù)或某個代碼段的耗時情況宏邮,那么該如何辦呢二庵?本文用兩種方式實(shí)現(xiàn)了代碼計時器的功能箭启,第一種方式是采用裝飾器來實(shí)現(xiàn)乾颁,第二種方式采用上下文管理器實(shí)現(xiàn)涂乌。
其實(shí)計算代碼的運(yùn)行時間,最樸素的想法就是先記錄下來某段代碼剛開始運(yùn)行時的時間英岭,等到運(yùn)行完之后湾盒,再看一下結(jié)束時的時間,最后和開始運(yùn)行時的時間求個差值诅妹,就是這段代碼所花費(fèi)的時間罚勾。
下面兩種計時器的實(shí)現(xiàn)方式就是用到這樣一種非常簡單的方法。
用裝飾器實(shí)現(xiàn)函數(shù)計時器
# coding:utf-8
from functools import wraps
import time
def func_timer(function):
'''
函數(shù)計時裝飾器
:param function: 裝飾的函數(shù)對象
'''
@wraps(function)
def function_timer(*args,**kwargs):
# 開始時間吭狡,單位:毫秒
t0 = time.time() * 1000
result = function(*args,**kwargs)
t1 = time.time() * 1000
print '[finish to invoke: {function}, spent: {time:.0f}ms]'.format(function = function.__name__,time = t1 - t0)
return result
return function_timer
@func_timer
def test(x,y):
s = x + y
time.sleep(1.5)
print 'the sum is: {0}'.format(s)
if __name__ == '__main__':
test(1,2)
# 輸出結(jié)果
'''
the sum is: 3
[finish to invoke: test1, spent: 1502ms]
'''
用上下文管理器實(shí)現(xiàn)代碼段計時器
上下文管理器其實(shí)是一個實(shí)現(xiàn)了__enter__
和__exit__
兩個特殊方法的對象尖殃,可以用with語法調(diào)用』螅可以參照操作文件的with oepn
操作送丰,比如:
with open('data.txt','r') as fin:
data = fin.read()
使用with上下文管理器操作文件的好處就是,不用擔(dān)心文件使用完之后忘記關(guān)閉弛秋,上下文管理器會自動幫你關(guān)閉器躏。
那么下面就用上下文管理器來實(shí)現(xiàn)一個代碼段計時器:
# coding:utf-8
from functools import wraps
import time
class FuncTimer(object):
'''
用上下文管理器實(shí)現(xiàn)代碼片段計時器
可以代替上面的func_timer來使用,而且還能適用于函數(shù)遞歸調(diào)用的場景
'''
def __init__(self,operation_name):
'''
初始化
:param operation_name: 操作名稱
'''
self.operation_name = operation_name
def __enter__(self):
self.t0 = time.time() * 1000
def __exit__(self,exc_type,exc_val,exc_tb):
self.t1 = time.time() * 1000
print '[finish to do: {operation_name}, spent: {time:.0f}ms]'.format(operation_name = self.operation_name,time = self.t1 - self.t0)
def test2():
time.sleep(0.8)
if __name__ == '__main__':
with FuncTimer('test2'):
test2()
# 輸出:
'''
[finish to do: test2, spent: 801ms]
'''
總結(jié)
可以看出蟹略,上述兩種計時器的實(shí)現(xiàn)方式各有優(yōu)缺點(diǎn)登失,用裝飾器實(shí)現(xiàn)的計時器優(yōu)點(diǎn)是使用起來非常方便,給要計時的函數(shù)加一個裝飾器即可挖炬,但不足之處是無法對一個代碼片段進(jìn)行計時揽浙。而用上下文管理器實(shí)現(xiàn)的計時器就可以對任意一個代碼段進(jìn)行計時,彌補(bǔ)了裝飾器計時器的缺陷。而且上下文管理器計時器還可以適用于函數(shù)遞歸調(diào)用的情況捏萍,而函數(shù)裝飾器計時器就不能用于有遞歸調(diào)用的函數(shù)太抓。
具體用哪種計時器,還是要根據(jù)實(shí)際情況來選擇令杈。
本文代碼:我的GitHub