Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"RuntimeError: This event loop is already running"; debugging aiohttp, asyncio and IDE "spyder3" in python 3.6.5

I'm struggling to understand why I am getting the "RuntimeError: This event loop is already running" runtime error. I have tried to run snippets of code from "https://aiohttp.readthedocs.io/en/stable/" however, I keep getting the same issue.

Code snippet from Tutorial:


import aiohttp
import asyncio
import async_timeout

async def fetch(session, url):
    async with async_timeout.timeout(10):
        async with session.get(url) as response:
            return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'http://python.org')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

RESULTS from tutorial snippet (while running code from spyder IDE):


RuntimeError: This event loop is already running

<!doctype html>"

... (more html)


Personal code snippet (not from the tutorial referenced above):


import aiohttp
import asyncio
import time

urls = ['https://api.robinhood.com/quotes/c4f6720a-0364-4e7b-8c41-705696759e1a/']

async def fetch(client, url):
    async with client.request('get', url) as response:
        if response.status == 200:
            data = await response.text()
        else:
            data = []
        print(data)
        return(data)

async def get_async_urls(urls):
    async with aiohttp.ClientSession() as client:
        return await asyncio.gather(*(fetch(client, url) for url in urls))

if __name__ == '__main__':
    t0 = time.time()
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(get_async_urls(urls))
    print(results)
    t1 = time.time()
    total_time = t1-t0
    loop.close()

RESULTS from personal snippet (while running code from spyder IDE):


RuntimeError: This event loop is already running

{"ask_price":"14.9000","ask_size":100,"bid_price":"14.0100","bid_size":100,"last_trade_price":"14.7900","last_extended_hours_trade_price":"14.7900","previous_close":"14.3600","adjusted_previous_close":"14.3600","previous_close_date":"2018-05-07","symbol":"SURF","trading_halted":false,"has_traded":true,"last_trade_price_source":"consolidated","updated_at":"2018-05-08T20:01:21Z","instrument":"https://api.robinhood.com/instruments/43d56335-f2f6-4711-b650-55be2396f814/"}


RESULTS from personal snippet (while running from cmd "python personal_snippet.py"):


{"ask_price":"14.9000","ask_size":100,"bid_price":"14.0100","bid_size":100,"last_trade_price":"14.7900","last_extended_hours_trade_price":"14.7900","previous_close":"14.3600","adjusted_previous_close":"14.3600","previous_close_date":"2018-05-07","symbol":"SURF","trading_halted":false,"has_traded":true,"last_trade_price_source":"consolidated","updated_at":"2018-05-08T20:01:21Z","instrument":"https://api.robinhood.com/instruments/43d56335-f2f6-4711-b650-55be2396f814/"} ['{"ask_price":"14.9000","ask_size":100,"bid_price":"14.0100","bid_size":100,"last_trade_price":"14.7900","last_extended_hours_trade_price":"14.7900","previous_close":"14.3600","adjusted_previous_close":"14.3600","previous_close_date":"2018-05-07","symbol":"SURF","trading_halted":false,"has_traded":true,"last_trade_price_source":"consolidated","updated_at":"2018-05-08T20:01:21Z","instrument":"https://api.robinhood.com/instruments/43d56335-f2f6-4711-b650-55be2396f814/"}']


The above results appear to point to the issue being related to the Spyder IDE.


I have two questions:

  1. Why am I getting this error? It seems like other people do not get this error when running the tutorial code. (Potentially answered: POSSIBLE BUG IN SPYDER3)

    This seems to only happen in the spyder IDE. I ran both snippets of code in from the cmd prompt and no error appeared. Thanks to @MikhailGerasimov for the suggestion.

  2. Given that I have two print commands (in the second snippet of code) and that only one set of "data" was printed, then why is data not getting back to the original call (results = loop.run_until_complete(get_async_urls(urls))) (Potentially answered: POSSIBLE BUG IN SPYDER3)

    This seems to only happen in the spyder IDE. I ran the second snippet of code in from the cmd prompt and both prints appeared. Thanks to @MikhailGerasimov for the suggestion.




BOTH QUESTIONS HAVE (probably) BEEN ANSWERED. I will reference this question when I submit an issue to spyder IDE. I will continue to update this as things evolve on the spyder side of things. If they come back and say the issue does not lie with them, then I will reopen the questions in a slightly different format.

Thanks for the help!




Link to the referenced issue submission in Spyder IDE's github: https://github.com/spyder-ide/spyder/issues/7096




like image 795
Ryan Baumgartner Avatar asked May 08 '18 23:05

Ryan Baumgartner


3 Answers

I have the same issue with Spyder, The only solution that worked for me was to use nest_asyncio

install the nest_asyncio by using the command

pip install nest_asyncio

Add the below lines in your file

import nest_asyncio
nest_asyncio.apply()

And the issue must be fixed.


From the docs's

By design asyncio does not allow its event loop to be nested. This presents a practical problem: When in an environment where the event loop is already running it’s impossible to run tasks and wait for the result. Trying to do so will give the error “RuntimeError: This event loop is already running”.

The issue pops up in various environments, such as web servers, GUI applications and in Jupyter notebooks.

This module patches asyncio to allow nested use of asyncio.run and loop.run_until_complete.

like image 135
Rajshekar Reddy Avatar answered Nov 13 '22 19:11

Rajshekar Reddy


Looks to me Spyder runs its own event loop. You cannot run two event loops in a single thread.

asyncio.run(coro, *, debug=False)

This function cannot be called when another asyncio event loop is running in the same thread.

This is what worked for me. I start my own loop if there is not other running loop:

import asyncio

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    await say_after(2, 'done')

await say_after(1, 'ahoy')    

loop = asyncio.get_event_loop()
print(loop) # <_WindowsSelectorEventLoop running=True closed=False debug=False>
if loop.is_running() == False:
    asyncio.run(main())
else:
    await main()
like image 37
Rav Avatar answered Nov 13 '22 18:11

Rav


The issue appears to be related to the IDE used (Spyder3). I tried running the code with PyCharm community edition last night. The code ran with no issues.

I have submitted a bug to Spyder3.

like image 3
Ryan Baumgartner Avatar answered Nov 13 '22 18:11

Ryan Baumgartner