20

Asyncio と aiohttp ライブラリを使用して一連のリクエスト (~1000) を作成しようとしていますが、多くの情報が見つからないという問題が発生しています。

このコードを 10 個の URL で実行すると、問題なく動作します。100以上のURLで実行すると、壊れてRuntimeError: Event loop is closedエラーが発生します。

import asyncio
import aiohttp


@asyncio.coroutine
def get_status(url):
    code = '000'
    try:
        res = yield from asyncio.wait_for(aiohttp.request('GET', url), 4)
        code = res.status
        res.close()
    except Exception as e:
        print(e)
    print(code)


if __name__ == "__main__":
    urls = ['https://google.com/'] * 100
    coros = [asyncio.Task(get_status(url)) for url in urls]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(coros))
    loop.close()

スタック トレースはここにあります。

私はこれについて数時間頭を悩ませてきたので、どんな助けや洞察も大歓迎です。明らかに、これはまだ開いているはずのイベントループが閉じられたことを示唆していますが、それがどのように可能かわかりません。

4

2 に答える 2

18

バグはhttps://github.com/python/asyncio/issues/258として登録されています 。

簡単な回避策として、カスタム executor を使用することをお勧めします。

loop = asyncio.get_event_loop()
executor = concurrent.futures.ThreadPoolExecutor(5)
loop.set_default_executor(executor)

プログラムを終了する前に行ってください

executor.shutdown(wait=True)
loop.close()
于 2015-09-16T17:43:03.237 に答える
7

そうです、loop.getaddrinfoは aを使用してスレッドでThreadPoolExecutor実行します。socket.getaddrinfo

タイムアウトでasyncio.wait_forを使用しています。つまり、4 秒後にres = yield from asyncio.wait_for...a が発生します。asyncio.TimeoutErrorその後、get_statusコルーチンが戻りNone、ループが停止します。その後ジョブが終了すると、イベント ループでコールバックをスケジュールしようとし、既に閉じられているため例外が発生します。

于 2015-09-16T14:26:32.070 に答える