优化测试 API 结果的 python 代码的速度
Optimizing speed of python code that tests results of an API
我正在尝试测试一个公开可用的网页,该网页接受 GET 请求和 returns 一个不同的 JSON 文件,具体取决于 GET 参数。
API看起来像
https://www.example.com/api/page?type=check&code=[Insert string here]
我编写了一个程序来检查此 API 上所有可能的 4 字母字符串的结果。我的代码看起来像这样(替换了实际的 URL):
import time, urllib.request
for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for b in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for d in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
a,b,c,d = "J","A","K","E"
test = urllib.request.urlopen("https://www.example.com/api/page?type=check&code=" + a + b + c + d).read()
if test != b'{"result":null}':
print(a + b + c + d)
f = open("codes", "a")
f.write(a + b + c + d + ",")
f.close()
此代码功能完备,按预期工作。但是,有一个问题。因为程序在收到响应之前无法进行,所以这种方法非常慢。如果 API 的此 ping 时间为 100ms,则每次检查将花费 100ms。当我修改此代码以便它可以在一个实例中测试一半结果,在另一个实例中测试一半结果时,我注意到速度翻了一番。
因此,我相信站点的 ping 时间是此脚本的限制因素。我想做的是能够基本上检查每个代码,然后立即检查下一个而不等待响应。
这相当于在我的浏览器中打开页面几千次。它可以同时加载多个选项卡,因为每个页面小于一千字节。
我研究过使用线程来执行此操作,但我不确定它是否相关或有用。
使用工作池,如下所述:https://docs.python.org/3.7/library/multiprocessing.html
from multiprocessing import Pool
def test_url(code):
''' insert code to test URL '''
pass
if __name__ == '__main__':
with Pool(5) as p:
print(p.map(test_url, [code1,code2,code3]))
请注意,该网站可能会限制您发出的请求数量。
为了更具体地说明您的示例,我会将其分为两个阶段:(1) 生成测试代码 (2) 测试url,给出一个测试代码。生成代码列表后,您可以使用工作池将验证器应用于每个生成的代码的上述策略。
要生成测试代码,您可以使用 itertools:
codes_to_test = [''.join(i) for i in itertools.product(string.ascii_lowercase, repeat = 5)]
您可以更好地理解如何在给定一个测试代码的情况下测试 URL,因此我假设您可以编写一个函数 test_url(test_code)
来发出适当的 URL 请求,并且必要时验证结果。然后你可以打电话:
with Pool(5) as p:
print(p.map(test_url, test_codes))
最重要的是,我建议两件事:首先确保 test_codes
不是很大(例如通过获取这些生成代码的子列表)以确保您的代码正常工作并且( 2) 您可以调整工作池的大小,以免使您的机器或 API.
不堪重负
或者,您可以使用 asyncio (https://docs.python.org/3/library/asyncio.html) 将所有内容保存在一个进程中。
我正在尝试测试一个公开可用的网页,该网页接受 GET 请求和 returns 一个不同的 JSON 文件,具体取决于 GET 参数。
API看起来像
https://www.example.com/api/page?type=check&code=[Insert string here]
我编写了一个程序来检查此 API 上所有可能的 4 字母字符串的结果。我的代码看起来像这样(替换了实际的 URL):
import time, urllib.request
for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for b in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
for d in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
a,b,c,d = "J","A","K","E"
test = urllib.request.urlopen("https://www.example.com/api/page?type=check&code=" + a + b + c + d).read()
if test != b'{"result":null}':
print(a + b + c + d)
f = open("codes", "a")
f.write(a + b + c + d + ",")
f.close()
此代码功能完备,按预期工作。但是,有一个问题。因为程序在收到响应之前无法进行,所以这种方法非常慢。如果 API 的此 ping 时间为 100ms,则每次检查将花费 100ms。当我修改此代码以便它可以在一个实例中测试一半结果,在另一个实例中测试一半结果时,我注意到速度翻了一番。
因此,我相信站点的 ping 时间是此脚本的限制因素。我想做的是能够基本上检查每个代码,然后立即检查下一个而不等待响应。
这相当于在我的浏览器中打开页面几千次。它可以同时加载多个选项卡,因为每个页面小于一千字节。
我研究过使用线程来执行此操作,但我不确定它是否相关或有用。
使用工作池,如下所述:https://docs.python.org/3.7/library/multiprocessing.html
from multiprocessing import Pool
def test_url(code):
''' insert code to test URL '''
pass
if __name__ == '__main__':
with Pool(5) as p:
print(p.map(test_url, [code1,code2,code3]))
请注意,该网站可能会限制您发出的请求数量。
为了更具体地说明您的示例,我会将其分为两个阶段:(1) 生成测试代码 (2) 测试url,给出一个测试代码。生成代码列表后,您可以使用工作池将验证器应用于每个生成的代码的上述策略。
要生成测试代码,您可以使用 itertools:
codes_to_test = [''.join(i) for i in itertools.product(string.ascii_lowercase, repeat = 5)]
您可以更好地理解如何在给定一个测试代码的情况下测试 URL,因此我假设您可以编写一个函数 test_url(test_code)
来发出适当的 URL 请求,并且必要时验证结果。然后你可以打电话:
with Pool(5) as p:
print(p.map(test_url, test_codes))
最重要的是,我建议两件事:首先确保 test_codes
不是很大(例如通过获取这些生成代码的子列表)以确保您的代码正常工作并且( 2) 您可以调整工作池的大小,以免使您的机器或 API.
或者,您可以使用 asyncio (https://docs.python.org/3/library/asyncio.html) 将所有内容保存在一个进程中。