2016-12-14 23 views
3

私はスクレイパー(Python 3.4.2とasyncio/aiohttp libsに基づいています)といくつかの少量のデータを取得するためのリンク(> 10K)を持っています。スクレーパーコードの パート:将来の例外が検索されませんでした

@asyncio.coroutine 
def prepare(self, links): 
    semaphore = asyncio.Semaphore(self.limit_concurrent) 
    tasks = [] 
    result = [] 

    tasks = [self.request_data(link, semaphore) for link in links] 

    for task in asyncio.as_completed(tasks): 
     response = yield from task 
     if response: 
      result.append(response) 
     task.close() 
    return result 

@asyncio.coroutine 
def request_data(self, link, semaphore): 

    ... 

    with (yield from semaphore): 
     while True: 
      counter += 1 
      if counter >= self.retry: 
       break 
      with aiohttp.Timeout(self.timeout): 
       try: 
        response = yield from self.session.get(url, headers=self.headers) 
        body = yield from response.read() 
        break 
       except asyncio.TimeoutError as err: 
        logging.warning('Timeout error getting {0}'.format(url)) 
        return None 
       except Exception: 
        return None 
    ... 

Whanそれは不正なURLのに要求を作ろうと、私はこのようなメッセージが出る:

Future exception was never retrieved 
future: <Future finished exception=gaierror(11004, 'getaddrinfo failed')> 
Traceback (most recent call last): 
    File "H:\Python_3_4_2\lib\concurrent\futures\thread.py", line 54, in run 
    result = self.fn(*self.args, **self.kwargs) 
    File "H:\Python_3_4_2\lib\socket.py", line 530, in getaddrinfo 
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags): 
socket.gaierror: [Errno 11004] getaddrinfo failed 

session.getからの応答を得るためにしようとしたときにエラーがoccures。私が理解しているように、例外はasyncioによって消費されていないので、「バブルアップ」ではありませんでした。

まず私は単にするtry/exceptで要求をラップするためにしようと試みた:これは動作しません

try: 
    response = yield from self.session.get(url, headers=self.headers) 
except Exception: 
    return None 

次に、コルーチンを連鎖させて例外を捕捉することについて、私はread hereでも、これは私にとってもうまくいきませんでした。私はまだ一定の時間が経過すると、それらのメッセージやスクリプトがクラッシュする。

私の質問 - どのように私はこの例外を適切に処理できますか?

答えて

1

あなたの質問に対する答えではありませんが、おそらくコードを動作させるかどうかに応じてどちらかの方法で解決することができます。

私はリクエストする前にURLSを検証します。私はいくつかのデータを収穫しようとしているこのような種類の頭痛をたくさん持っていたので、それらを先に修正し、不正な形式のURLをログに記録することに決めました。

djangoの正規表現や他のコードを使用すると、公開されているので、これを行うことができます。

この質問では、人はdjangoの検証正規表現を与えます。 Python - How to validate a url in python ? (Malformed or not)

+0

はい、私はその方向を見ていましたが、他に問題があります。小規模な調査では、このエラーの原因となるリンクのすべてが不正な形式であるとは限りません。その中には、httpの代わりにリダイレクトやWebSocketのサーバだけがあるものもあります。この場合、例外を捕捉できる方が良いと思います。 – Charnel

+1

おそらく、以下に述べる方法でデバッグトレースバックを投稿することができます: https://docs.python.org/3/library/asyncio-dev.html#detect-exceptions-never-consumed もっと詳しい情報が必要です正確にそれを引き起こしているもの。 いずれにしても、幸運にも、スクレーパーは維持して走り続ける悪夢になることがあります^^ – user7296055

関連する問題