我想以最快的方式发出数千个POST请求.我怎么能用Python做到这一点?
到目前为止,我只有一个for循环,它多次调用以下函数:
def post(word):
data = json.dumps({"word":word})
url = "http://127.0.0.1:8000/updateword"
req = urllib2.Request(url, data, {'Content-Type': 'application/octet-stream'})
response=None
try:
f = urllib2.urlopen(req)
response = f.read()
f.close()
except urllib2.HTTPError, error:
k= open('error.html','w')
k.write(error.read())
k.close()
return response
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
您编写代码的方式,它会在发送下一个请求之前等待对一个请求的响应.(最重要的是,它可能无法重用HTTP连接,这意味着您必须处理每个请求的套接字创建/关闭开销.然后,根据您正在测试的内容,实际上它很可能成为一个更好的测试.)
同时发出多个请求的最简单方法是使用线程.最简单的方法是使用concurrent.futures(或者futures从PyPI,如果你使用的是2.x或3.1):
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as pool:
results = pool.map(post, words)
concurrent.futures.wait(results)
Run Code Online (Sandbox Code Playgroud)
如果你愿意,你可以编写自己的线程,只需给每个线程1/10,words并让它循环调用post:
def posts(words):
for word in words:
post(word)
groupsize = len(words)/10
t = [threading.Thread(target=posts, args=[words[i*groupsize:(i+1)*groupsize]]
for i in range(10)]
for thread in t:
thread.start()
for thread in t:
thread.join()
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,显然我只是凭空掏出这个数字10(因为它比大多数浏览器或Web服务客户端允许你创建的最大同时连接多一点),但是你会想做一些性能测试来查找最好的价值.
如果事实证明最好的价值是巨大的,比如500或者其他东西,那么你可能会遇到使用线程可以做的极限.在这种情况下,您应该考虑使用greenlets.最简单的方法是使用gevent- 最简单的方法是重写代码以grequests代替使用urllib2.
同时,如果实际读取浪费时间,并且您实际上不需要响应,并且它们相当大,并且您没有尝试测试服务器发送实际响应的能力,您可能想要关闭套接字一旦你知道你将获得正确的数据.您可以urllib2通过编写自己的处理程序来完成此操作,但这听起来像是很多工作.我认为在这种情况下实际上更简单,只需降低到套接字的级别.首先,记录为每个POST发送的请求,以及在事情有效时返回的预期200行.然后做这样的事情:
with closing(socket.socket()) as c:
c.connect(('127.0.0.1', 8000))
c.send(REQUEST_STRING_FORMAT.format([word]))
with c.makefile() as f:
response = f.readline()
if response != RESPONSE_200_STRING:
response += f.read()
with open('error.html','w') as k:
k.write(response)
Run Code Online (Sandbox Code Playgroud)