Greg
Greg

Reputation: 8915

How to treat and deal with event loops?

Is a loop.close() needed prior to returning async values in the below code?

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]))

That is, should fetch_urls be like this instead?:

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

If the loop.close() is needed, then how can fetch_urls be called again without raising the exception: RuntimeError: Event loop is closed?

A previous post states that it is good practice to close the loops and start new ones however it does not specify how new loops can be opened?

Upvotes: 1

Views: 146

Answers (2)

Udi
Udi

Reputation: 30472

You can also keep the event loop alive, and close it the end of your program, using run_until_complete more than once:

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()

Upvotes: 2

Ethan Furman
Ethan Furman

Reputation: 69031

No, the async function (request in this case) should not be closing the event loop. The command loop.run_until_complete will close stop the event loop as soon as it runs out of things to do.

fetch_urls should be the second version -- that is, it will get an event loop, run the event loop until there is nothing left to do, and then closes it loop.close().

Upvotes: 1

Related Questions