如何对待和应对事件循环?

How to treat and deal with event loops?

在下面的代码中返回异步值之前是否需要 loop.close()

import asyncio

async def request_url(url):
    return url

def fetch_urls(x):
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(asyncio.gather(*[request_url(url) for url in x]))

也就是说,fetch_urls应该是这样的吗?:

def fetch_urls(x):
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*[request_url(url) for url in x]))
    loop.close()
    return results

如果需要 loop.close(),那么如何在不引发异常的情况下再次调用 fetch_urlsRuntimeError: Event loop is closed?

A 指出关闭循环并开始新循环是一种很好的做法,但它没有指定如何打开新循环?

不,异步函数(在本例中为request)不应该关闭事件循环。命令 loop.run_until_complete 关闭 停止事件循环,一旦它 运行 没有事情要做。

fetch_urls应该是第二个版本——就是会得到一个事件循环,运行事件循环直到无事可做,然后关闭loop.close().

您还可以使事件循环保持活动状态,并在程序结束时将其关闭,多次使用 run_until_complete

import asyncio


async def request_url(url):
    return url


def fetch_urls(loop, urls):
    tasks = [request_url(url) for url in urls]
    return loop.run_until_complete(asyncio.gather(*tasks, loop=loop))


loop = asyncio.get_event_loop()
try:
    print(fetch_urls(loop, ['a1', 'a2', 'a3']))
    print(fetch_urls(loop, ['b1', 'b2', 'b3']))
    print(fetch_urls(loop, ['c1', 'c2', 'c3']))
finally:
    loop.close()