python|获取接口请求耗时

简介: python|获取接口请求耗时

image.png

你想知道我们请求一个url的时候,握手和请求资源分别占用多长时间么?今天我们使用python写个小案例来看看吧。

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("执行命令为: %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("接口状态码为:" , responseInfo[0],"握手耗时: %.6fs" %(shakeInfo[1]) , "请求接口耗时: %.6fs" %(responseInfo[1]) ,"总共耗时为: %.6fs" % (shakeInfo[1] + responseInfo[1]))
if __name__ == '__main__':
    main()


项目中使用了python装饰器,若还对python装饰器不太了解的小伙伴,可以参考一下下面这篇文章:

python | 探寻python装饰器: juejin.cn/post/722093…




项目展示


打开项目,修改hostsportmethods以及url的变量,即可运行python程序便可获得该页面的详细信息的时间,其中包括TCP/IP三次握手时间 以及 请求接口耗时,最后是 总的耗时,

image.png


如何获得握手时间

在获取握手时间的时候,不能使用http库,例如: requests,因为它默认会进行tcp/ip三次握手,而后再进行资源请求,所以我们要使用socket来做这个需求。

python中,socket提供了一种跨平台的网络通信接口,可以用它来创建各种类型的网络连接。

例如代码如下:


import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8080))

在上面的代码中,我们先导入socket库,而后使用socket.socket()创建一个socket句柄,而中间的参数分别代表的意思为:

  • socket.AF_INET: 指定IPv4协议。
  • socket.SOCK_STREAM: 指定使用TCP流式套接字类型。

s.connect则开始连接服务器,其参数类型为元组类型,参数值为远程主机名 和 远程端口。


如上代码,当远程服务器连不上的时候或者其他异常的时候,该代码会抛异常,若没有异常,则证明端口通的。


我们仅需要在此之前和之后,都拉一下当前时间戳,就可以计算出握手所耗费的时间,例如:


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)

若没有抛错,我们即可获得握手时间。



如何获得请求时间


握手成功后,我们就可以向该服务器发送http报文了,注意最简单报文的格式是:

请求方法 请求路由 版本号

请求头(主机名)

空行


例如:

GET / HTTP/1.1
Host: 127.0.0.1:8080


如果我们不添加Host请求头,则会抛错: HTTP/1.1 400 Bad Request: missing required Host header


python中,我们直接使用s.send()函数即可发送请求,例如:

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个\r\n是有一个空行,来标志http请求头的结束。


一般来说,我们请求接口后,会读取服务器返回来的状态码,以便开发验证是否是成功的。


这里可以使用s.recv()函数来读取服务器传回来的信息,例如读取从服务器返回的15个字节s.recv(15)

我们可以参考计算握手时间的方法,来计算一下资源请求的时间,代码如下:

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,"接口返回状态码: " , recv_data.split(" ")[1])



如果远程主机和远程端口都正常的话,我们大概会得到如下的信息:

image.png


善用装饰器


我们计算握手时间,和计算资源请求时间,都是相同的代码,因为计算的功能不同,所以我们需要被迫写2次,这个时候,就可以使用装饰器,来把这个额外非核心功能给抽离出来,而将计算握手和计算资源请求都给封装为函数,而后通过函数来调用装饰器,就可以获取2种请求时间了。


我们先将装饰器抽离出来:

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函数,而在wrapper函数中,定义开始时间和结束时间,在二者的中间执行函数func,最后将func的结果以及函数执行的时间封装为一个元组进行返回。


此时,我们可以封装函数了,例如我们想获取握手的时间,我们可以这样写:

@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


如果该远程主机可以连上,我们直接返回socket句柄,若连接不上,直接打印错误,返回None

调用该函数的是,我们接收返回值即可:

shakeInfo = shakeHands(hosts,port)

注意,shakeInfo是一个元组,有2个元组,第一个是socket句柄,第二个是执行该函数所需要的时间。

我们再将资源请求函数封装一下,就可以完成这个项目了。



总结


我们使用python socket连接服务器,以及发送http报文,再计算2个函数所执行的时间,便可以获取到握手和资源请求的时间了,最后再将获取时间的函数提取出来,封装为装饰器,供函数调用,即可得到函数的执行时间了。


相关文章
|
20天前
|
JSON API 开发者
Python网络编程新纪元:urllib与requests库,让你的HTTP请求无所不能
【7月更文挑战第31天】互联网的发展使网络编程成为软件开发的关键部分. Python以简洁、功能强大著称, 在此领域尤显突出. `urllib`作为标准库, 自Python初期便支持URL处理, 如读取URL (`urllib.request`) 和解析 (`urllib.parse`). 尽管API底层, 但奠定了网络编程基础.
34 4
|
3天前
|
JSON API 数据格式
Python网络编程:HTTP请求(requests模块)
在现代编程中,HTTP请求几乎无处不在。无论是数据抓取、API调用还是与远程服务器进行交互,HTTP请求都是不可或缺的一部分。在Python中,requests模块被广泛认为是发送HTTP请求的最简便和强大的工具之一。本文将详细介绍requests模块的功能,并通过一个综合示例展示其应用。
|
8天前
|
开发者 Python
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
21 1
|
11天前
|
JSON API 开发者
Python学习Get方式通过商品 ID请求 获取拼多多商品详情数据接口
拼多多商品详情数据接口服务使开发者或商家能编程获取平台商品详情,涵盖标题、价格、销量等关键信息,助力市场分析与决策。使用前需注册开发者账号并获取API密钥;构造含商品ID等参数的请求URL后发送至API服务器;接口以JSON格式返回数据。应用场景包括商品销售分析、选品、品牌口碑挖掘及竞品分析,为商家提供强大数据支持。
|
20天前
|
存储 运维 Java
函数计算产品使用问题之如何使用Python的requests库向HTTP服务器发送GET请求
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
28天前
|
API 数据安全/隐私保护 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
【7月更文挑战第23天】Python的RESTful API设计在Web开发中流行,提升效率与体验。REST强调HTTP方法(GET, POST, PUT, DELETE)操作资源。使用Flask框架可快速实现API,如管理用户信息。示例代码展示如何创建、读取、更新和删除用户,通过不同HTTP方法和URL路径。实际应用中,增加验证、错误处理和权限控制可增强API的安全性和稳定性。安装Flask后,可运行代码测试API功能。
53 6
|
5天前
|
API Python
在线问诊 Python、FastAPI、Neo4j — 提供咨询接口服务
在线问诊 Python、FastAPI、Neo4j — 提供咨询接口服务
10 0
|
29天前
|
安全 API 网络架构
Python RESTful API设计新篇章,打造高效、易用、安全的Web服务接口,你准备好了吗?
【7月更文挑战第22天】在数字化转型中,RESTful API借助Python的Flask和Django REST Framework,提供高效、易用和安全的接口设计。Flask示例展示了简洁的CRUD操作,Swagger等工具增进API文档的易用性,而HTTPS、JWT和输入验证确保安全性。Python RESTful API设计涉及效率、可用性和安全,是不断进化的Web服务接口的关键。准备好踏上这一新篇章了吗?一起探索,创造卓越!
35 2
|
1月前
|
Java API Python
python并发执行request请求
选择哪种并发方式取决于我们的具体需求。对于I/O密集型任务,多线程或异步I/O通常是更好的选择;对于CPU密集型任务,多进程可能是更好的选择。此外,异步I/O通常比多线程具有更好的性能,特别是在高并发的网络应用中。
|
1月前
|
监控 网络协议 安全
由于楼层自动化系统的复杂性和多样性,很难给出一个通用的Python代码示例,因为每个系统可能使用不同的硬件、通信协议和软件接口。
由于楼层自动化系统的复杂性和多样性,很难给出一个通用的Python代码示例,因为每个系统可能使用不同的硬件、通信协议和软件接口。