2016-02-22 1 views
0

У меня есть следующий код:Обработка исключений для параллельных запросов выборки

try: 
    responses = yield [httpClient.fetch(url) for url in urls] 
    except (HTTPError, IOError, ValueError) as e: 
    print("caught") 

Я не могу гарантировать, что URLs данные действительны. Я хочу иметь возможность использовать исключение для проверки URL-адресов. Как я могу определить, какие url (ы) не выполняются в пойманном исключении?

Также, если одна из неудачных попыток (скажем, первая), похоже, что она ломается для остальной выборки? Есть ли способ предотвратить это? Или есть лучший способ проверить, что URL-адрес может быть получен до фактического получения? Есть ли лучший образец для этого. В принципе, я хочу получить все URL-адреса параллельно и узнать, какой из них потенциально терпит неудачу.

ответ

4

Наиболее простым решением является передача raise_error=False в fetch(). Это всегда даст вам ответ, и вы будете иметь возможность осмотреть response.error или использовать response.rethrow():

responses = yield [httpClient.fetch(url, raise_error=False) for url in urls] 
for url, resp in zip(urls, responses): 
    try: 
     resp.rethrow() 
     print("succeeded") 
    except (HTTPError, IOError, ValueError) as e: 
     print("caught") 
1

Я думал о выполнении следующих действий:

 @tornado.gen.coroutine 
     def wrap(httpClient,url): 
     try: 
      response=yield httpClient.fetch(url) 
     except (HTTPError, IOError, ValueError,StopIteration) as e: 
      return e 
     return response 



     httpClient=AsyncHTTPClient() 
     responses=yield [wrap(httpClient,url) for url in urls] 

Есть ли лучше или более элегантный способ? Это также часть функции, которая уже украшена @ tornado.gen.coroutine, которая будет представлять проблему?

1

Подход в вашем ответе в порядке, еще более изящный, на первый взгляд, чем у Торнадо. WaiterIterator - это «справочное» решение для обработки таких ситуаций. Я завернут пример DOC смерча как:

from tornado.ioloop import IOLoop 
from tornado.gen import coroutine, WaitIterator 
from tornado.httpclient import AsyncHTTPClient, HTTPError 

@coroutine 
def multi_exc_safe(futures): 
    multi = {} 
    wait_iterator = WaitIterator(*futures) 
    while not wait_iterator.done(): 
     try: 
      res = yield wait_iterator.next() 
      multi[wait_iterator.current_index] = res 
     except (HTTPError, IOError, ValueError,StopIteration) as e: 
      multi[wait_iterator.current_index] = e 
    return multi 

@coroutine 
def main(): 
    urls = [ 
     'http://google.com', 
     'http://nnaadswqeweqw342.comm', 
    ] 
    httpclient = AsyncHTTPClient() 
    responses = yield multi_exc_safe([httpclient.fetch(url) for url in urls]) 
    print(responses) 

IOLoop.instance().run_sync(main) 

Прохладной вещь (вероятно, не имеет отношения к вашей проблеме) о WaiterIterator есть, это итератор :). Он позволяет получать ответы как можно скорее и работает как шарм с async for.

+0

Спасибо за это! Я не знал об этом;) –