asyncio.run () не может быть вызван из цикла работающего события - PullRequest
3 голосов
/ 29 марта 2019

Я бы хотел использовать asyncio для получения html веб-страницы.

Я запускаю следующий код в блокноте jupyter:

import aiofiles
import aiohttp
from aiohttp import ClientSession

async def get_info(url, session):
    resp = await session.request(method="GET", url=url)
    resp.raise_for_status()
    html = await resp.text(encoding='GB18030')
    with open('test_asyncio.html', 'w', encoding='utf-8-sig') as f:
        f.write(html)
    return html

async def main(urls):
    async with ClientSession() as session:
        tasks = [get_info(url, session) for url in urls]
        return await asyncio.gather(*tasks)

if __name__ == "__main__":
    url = ['http://huanyuntianxiazh.fang.com/house/1010123799/housedetail.htm', 'http://zhaoshangyonghefu010.fang.com/house/1010126863/housedetail.htm']
    result = asyncio.run(main(url))

Однако возвращается RuntimeError: asyncio.run() cannot be called from a running event loop

В чем проблема?

Как это решить?

Большое спасибо.

1 Ответ

9 голосов
/ 29 марта 2019

Документация asyncio.run () гласит:

Эту функцию нельзя вызвать, если в том же потоке выполняется другой цикл событий asyncio.

Проблема в вашем случае заключается в том, что jupyter (IPython) уже выполняет цикл обработки событий (для IPython ≥ 7.0 ):

Теперь вы можете использовать async / await вверхний уровень в терминале IPython и в ноутбуке должен - в большинстве случаев - «просто работать».Обновите IPython до версии 7+, IPykernel до версии 5+, и вы готовы к гонкам.

Вот почему вам не нужно запускать цикл событий самостоятельно в jupyter, и вы можете напрямую позвонить await main(url).

В jupyter

async def main():
    print(1)

await main()

В простом Python (≥3.7)

import asyncio

async def main():
    print(1)

asyncio.run(main())

В вашем коде это даст:

if __name__ == "__main__":
    url = ['url1', 'url2']
    result = await main(url)
    for text in result:
        pass # text contains your html (text) response
...