2016-08-16 2 views
0

항목 목록을 가져 와서 API의 특정 처리를 기반으로 상태 변경을 확인하려고합니다. 목록은 수동으로 채워지며 수천 개로 다양 할 수 있습니다.여러 개의 동시 HTTP 요청

상태 변경을 계속 확인하기 위해 API에 여러 개의 동시 연결을 만드는 스크립트를 작성하려고합니다. 각 항목에 대해 상태가 변경되면 검사 시도가 중지되어야합니다. Stackoverflow (특히, What is the fastest way to send 100,000 HTTP requests in Python?)에 다른 게시물을 읽고 기반으로, 나는 다음과 같은 코드를 마련했습니다. 그러나 스크립트는 목록을 한 번 처리 한 후에는 항상 중지됩니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

내가 직면하고있어 하나의 추가 문제는 키보드 interrup 방법은 내가 파이썬에 새로 온 사람 (내가 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) 

터지지 않 것입니다 그래서 구문 오류도있을 수 있습니다 ... 나는 확실히 멀티 스레딩에 익숙하지 않습니다. 그래서 아마도 다른 잘못된 것도하고 있습니다.

답변

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을 포함하여 모든 예외를 catch합니다. 이는 sys.exit이 발생하여 파이썬 프로세스가 종료되는 것을 중지시킵니다.

비록 내가 일반적으로 몇 가지 의견을 낼 수 있다면.

  • 스레딩마다 새로운 연결을 생성 대형 concurrencies
  • 에 대한 좋은 구현되지 않습니다 내가 제안 무엇

  • 사용 gevent for asynchronous network I/O

    1. 입니다 효율적이지 않습니다 동시성 번호와 동일한 크기의 연결 대기열을 미리 할당하고 checkStatus 잡기 전화를 걸 때 연결 개체. 연결이 살아남은 상태에서 재사용하면 오버 헤드가 생기지 않으며이를 파괴하고 메모리 사용량도 증가합니다.
  • 관련 문제