按照您编写代码的方式,它会在发送下一个请求之前等待对一个请求的响应。(最重要的是,它可能不会重用 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)
如果您愿意,您可以编写自己的线程,并只给每个线程 1/10words
并让它循环调用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()
无论哪种方式,显然我只是凭空取出了第 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)