2016-08-16 173 views
0

我在尝试获取项目列表,并根据API的某些处理检查其状态更改。该列表将手动填充,数量可能会有所不同。多个同时发出的HTTP请求

我想写一个脚本,使多个同时连接到API,以保持检查状态更改。对于每个项目,一旦状态改变,就必须停止尝试检查。根据阅读其他帖子Stackoverflow(具体来说,What is the fastest way to send 100,000 HTTP requests in Python?),我想出了以下代码。但脚本总是在处理完列表后停止。我究竟做错了什么?

,我现在面临一个额外的问题是,键盘中断程序方法永远不会触发(我想用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所以可能会出现语法错误......我绝对不熟悉多线程,所以我也可能会做其他事情。

回答

0

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

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. 使用gevent for asynchronous network I/O
  2. 预先分配一个与并发号码大小相同的连接队列,并且拥有checkStatus一个连接对象,当它需要拨打电话。这样,连接保持活跃状态​​,得到重用,并且在创建和销毁它们以及随之增加内存使用方面没有任何开销。