多个同时的HTTP请求



我试图采取项目列表,并检查他们的状态变化基于某些处理的API。该列表将手动填充,数量可以变化到几千个。

我试图写一个脚本,使多个同时连接到API,以保持检查状态的变化。对于每个项目,一旦状态改变,检查的尝试必须停止。基于阅读Stackoverflow上的其他帖子(具体来说,在Python中发送100,000个HTTP请求的最快方法是什么?),我编写了以下代码。但是脚本总是在处理列表一次之后停止。我做错了什么?

我面临的另一个问题是键盘中断方法永远不会触发(我正在尝试使用Ctrl+C,但它不会杀死脚本。

from urlparse import urlparse
from threading import Thread
import httplib, sys
from Queue import Queue
requestURLBase = "https://example.com/api"
apiKey = "123456"
concurrent = 200
keepTrying = 1
def doWork():
    while keepTrying == 1:
        url = q.get()
        status, body, url = checkStatus(url)
        checkResult(status, body, url)
        q.task_done()
def checkStatus(ourl):
    try:
        url = urlparse(ourl)
        conn = httplib.HTTPConnection(requestURLBase)
        conn.request("GET", url.path)
        res = conn.getresponse()
        respBody = res.read()
        conn.close()
        return res.status, respBody, ourl #Status can be 210 for error or 300 for successful API response
    except:
        print "ErrorBlock"
        print res.read()
        conn.close()
        return "error", "error", ourl
def checkResult(status, body, url):
    if "unavailable" not in body:
        print status, body, url
        keepTrying = 1
    else:
        keepTrying = 0
q = Queue(concurrent * 2)
for i in range(concurrent):
    t = Thread(target=doWork)
    t.daemon = True
    t.start()
try:
    for value in open('valuelist.txt'):
        fullUrl = requestURLBase + "?key=" + apiKey + "&value=" + value.strip() + "&years="
        print fullUrl
        q.put(fullUrl)
    q.join()
except KeyboardInterrupt:
    sys.exit(1)

我是Python的新手,所以也可能有语法错误…我肯定不熟悉多线程,所以也许我做错了其他的东西,以及

在代码中,该列表只被读取一次。应该是像

try:
    while True:
        for value in open('valuelist.txt'):
            fullUrl = requestURLBase + "?key=" + apiKey + "&value=" + value.strip() + "&years="
            print fullUrl
            q.put(fullUrl)
        q.join()

对于中断的事情,删除checkStatus中的裸except行或使其为except Exception。裸异常将捕获所有异常,包括SystemExit,这是sys.exit引发的,并阻止python进程终止。

如果我可以做一些一般性的评论。

  • 对于如此大的并发来说,线程不是一个很好的实现
  • 每次都创建新连接效率不高

我的建议是

  1. 异步网络I/O使用gevent
  2. 预先分配一个与并发数相同大小的连接队列,并在需要调用时让checkStatus抓取连接对象。这样,连接保持活跃,被重用,并且没有创建和销毁它们的开销,也没有随之增加的内存使用。

相关内容

  • 没有找到相关文章

最新更新