Python獲取接口請求耗時(shí)的方法詳解
你想知道我們請求一個(gè)url
的時(shí)候,握手和請求資源分別占用多長時(shí)間么?今天我們使用python
寫個(gè)小案例來看看吧。
import socket import time def funcRunTimes(func): def wrapper(*args): startTime = time.time() result = func(*args) endTime = time.time() execTime = endTime - startTime return (result,execTime) return wrapper @funcRunTimes def shakeHands(hosts,port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((hosts, port)) return s except Exception as e: print(e) return None @funcRunTimes def websiteResponseTime(fd,methods,url): sendMsgs = "%s %s HTTP/1.1\r\nHost: 127.0.0.1:8080\r\n\r\n" %(methods,url) fd.send(sendMsgs.encode()) recv_data = "" while True: recv_data = str(fd.recv(15)) break httpCode = recv_data.split(" ")[1] return httpCode def main(): hosts = "www.juejin.cn" port = 80 methods = "GET" url = "/" print("執(zhí)行命令為: %s %s:%d %s\n" % (methods, hosts, port, url)) shakeInfo = shakeHands(hosts,port) if shakeInfo == None: print("errors") return responseInfo = websiteResponseTime(shakeInfo[0],methods,url) print("接口狀態(tài)碼為:" , responseInfo[0],"握手耗時(shí): %.6fs" %(shakeInfo[1]) , "請求接口耗時(shí): %.6fs" %(responseInfo[1]) ,"總共耗時(shí)為: %.6fs" % (shakeInfo[1] + responseInfo[1])) if __name__ == '__main__': main()
項(xiàng)目中使用了python
裝飾器,若還對python
裝飾器不太了解的小伙伴,可以參考一下下面這篇文章:python | 探尋python裝飾器
項(xiàng)目展示
打開項(xiàng)目,修改hosts
、port
、methods
以及url
的變量,即可運(yùn)行python
程序便可獲得該頁面的詳細(xì)信息的時(shí)間,其中包括TCP/IP
三次握手時(shí)間 以及 請求接口耗時(shí),最后是 總的耗時(shí),
如何獲得握手時(shí)間
在獲取握手時(shí)間的時(shí)候,不能使用http
庫,例如: requests
,因?yàn)樗J(rèn)會進(jìn)行tcp/ip
三次握手,而后再進(jìn)行資源請求,所以我們要使用socket
來做這個(gè)需求。
在python
中,socket
提供了一種跨平臺的網(wǎng)絡(luò)通信接口,可以用它來創(chuàng)建各種類型的網(wǎng)絡(luò)連接。
例如代碼如下:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 8080))
在上面的代碼中,我們先導(dǎo)入socket
庫,而后使用socket.socket()
創(chuàng)建一個(gè)socket
句柄,而中間的參數(shù)分別代表的意思為:
socket.AF_INET
: 指定IPv4
協(xié)議。socket.SOCK_STREAM
: 指定使用TCP
流式套接字類型。
而s.connect
則開始連接服務(wù)器,其參數(shù)類型為元組類型,參數(shù)值為遠(yuǎn)程主機(jī)名 和 遠(yuǎn)程端口。
如上代碼,當(dāng)遠(yuǎn)程服務(wù)器連不上的時(shí)候或者其他異常的時(shí)候,該代碼會拋異常,若沒有異常,則證明端口通的。
我們僅需要在此之前和之后,都拉一下當(dāng)前時(shí)間戳,就可以計(jì)算出握手所耗費(fèi)的時(shí)間,例如:
import socket import time try: startTime = time.time() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 8080)) endTime = time.time() print("runtimes: " , endTime-startTime) except Exception as e: print("捕獲異常" , e)
若沒有拋錯(cuò),我們即可獲得握手時(shí)間。
如何獲得請求時(shí)間
握手成功后,我們就可以向該服務(wù)器發(fā)送http
報(bào)文了,注意最簡單報(bào)文的格式是:
請求方法 請求路由 版本號
請求頭(主機(jī)名)
空行
例如:
GET / HTTP/1.1
Host: 127.0.0.1:8080
如果我們不添加Host
請求頭,則會拋錯(cuò): HTTP/1.1 400 Bad Request: missing required Host header
。
在python
中,我們直接使用s.send()
函數(shù)即可發(fā)送請求,例如:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 8080)) s.send(b"GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\n\r\n")
上述代碼中,\r\n
是換行的意思,也稱之為CRLF
,注意最后的2個(gè)\r\n
是有一個(gè)空行,來標(biāo)志http
請求頭的結(jié)束。
一般來說,我們請求接口后,會讀取服務(wù)器返回來的狀態(tài)碼,以便開發(fā)驗(yàn)證是否是成功的。
這里可以使用s.recv()
函數(shù)來讀取服務(wù)器傳回來的信息,例如讀取從服務(wù)器返回的15個(gè)字節(jié)s.recv(15)
。
我們可以參考計(jì)算握手時(shí)間的方法,來計(jì)算一下資源請求的時(shí)間,代碼如下:
import socket import time s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 8080)) startTime = time.time() s.send(b"GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\n\r\n") recv_data = str(s.recv(15)) endTime = time.time() print("runtimes: ", endTime - startTime,"接口返回狀態(tài)碼: " , recv_data.split(" ")[1])
如果遠(yuǎn)程主機(jī)和遠(yuǎn)程端口都正常的話,我們大概會得到如下的信息:
善用裝飾器
我們計(jì)算握手時(shí)間,和計(jì)算資源請求時(shí)間,都是相同的代碼,因?yàn)橛?jì)算的功能不同,所以我們需要被迫寫2次,這個(gè)時(shí)候,就可以使用裝飾器,來把這個(gè)額外非核心功能給抽離出來,而將計(jì)算握手和計(jì)算資源請求都給封裝為函數(shù),而后通過函數(shù)來調(diào)用裝飾器,就可以獲取2種請求時(shí)間了。
我們先將裝飾器抽離出來:
def funcRunTimes(func): def wrapper(*args): startTime = time.time() result = func(*args) endTime = time.time() execTime = endTime - startTime return (result,execTime) return wrapper
我們在funcRunTimes
中直接返回wrapper
函數(shù),而在wrapper
函數(shù)中,定義開始時(shí)間和結(jié)束時(shí)間,在二者的中間執(zhí)行函數(shù)func
,最后將func
的結(jié)果以及函數(shù)執(zhí)行的時(shí)間封裝為一個(gè)元組進(jìn)行返回。
此時(shí),我們可以封裝函數(shù)了,例如我們想獲取握手的時(shí)間,我們可以這樣寫:
@funcRunTimes def shakeHands(hosts,port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((hosts, port)) return s except Exception as e: print(e) return None
如果該遠(yuǎn)程主機(jī)可以連上,我們直接返回socket
句柄,若連接不上,直接打印錯(cuò)誤,返回None
。
調(diào)用該函數(shù)的是,我們接收返回值即可:
shakeInfo = shakeHands(hosts,port)
注意,shakeInfo
是一個(gè)元組,有2個(gè)元組,第一個(gè)是socket
句柄,第二個(gè)是執(zhí)行該函數(shù)所需要的時(shí)間。
我們再將資源請求函數(shù)封裝一下,就可以完成這個(gè)項(xiàng)目了。
總結(jié)
我們使用python socket
連接服務(wù)器,以及發(fā)送http
報(bào)文,再計(jì)算2個(gè)函數(shù)所執(zhí)行的時(shí)間,便可以獲取到握手和資源請求的時(shí)間了,最后再將獲取時(shí)間的函數(shù)提取出來,封裝為裝飾器,供函數(shù)調(diào)用,即可得到函數(shù)的執(zhí)行時(shí)間了。
到此這篇關(guān)于Python獲取接口請求耗時(shí)的方法詳解的文章就介紹到這了,更多相關(guān)Python接口請求耗時(shí)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中使用select模塊實(shí)現(xiàn)非阻塞的IO
這篇文章主要介紹了Python中使用select模塊實(shí)現(xiàn)非阻塞的IO,本文使用一個(gè)簡單聊天室程序講解Python中的select模塊使用,需要的朋友可以參考下2015-02-02PIL.Image.open和cv2.imread的比較與相互轉(zhuǎn)換的方法
這篇文章主要介紹了PIL.Image.open和cv2.imread的比較與相互轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06python獲取指定日期范圍內(nèi)的每一天,每個(gè)月,每季度的方法
這篇文章主要介紹了python獲取指定日期范圍內(nèi)的每一天,每個(gè)月,每季度的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08python用循環(huán)新建多個(gè)列表的代碼實(shí)例
當(dāng)我們處理數(shù)據(jù)時(shí),有時(shí)候需要?jiǎng)?chuàng)建多個(gè)列表以存儲不同類型或不同條件下的數(shù)據(jù),在Python中,我們可以利用循環(huán)來快速、高效地創(chuàng)建這些列表,本文將介紹如何使用循環(huán)在Python中創(chuàng)建多個(gè)列表,并提供代碼實(shí)例,需要的朋友可以參考下2024-04-04Python的Flask框架中實(shí)現(xiàn)登錄用戶的個(gè)人資料和頭像的教程
這篇文章主要介紹了Python的Flask框架中實(shí)現(xiàn)登錄用戶的個(gè)人資料和頭像的教程,這也是各個(gè)web框架的最基本功能之一,需要的朋友可以參考下2015-04-04Python中橫向或縱向拼接兩個(gè)表方法實(shí)例
最近要將兩個(gè)表格合并,Python處理起來很簡單,所以這篇文章主要給大家介紹了關(guān)于Python中橫向或縱向拼接兩個(gè)表的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07