Reputation: 481
It is a very common issue, but I cannot actually find a proper answer to it. I have the following code to connect to a server through a websocket and I want to keep it alive and keep listening to messages it sends like below:
import asyncio
import websockets
import nest_asyncio
nest_asyncio.apply()
async def listen_for_message(websocket):
while True:
await asyncio.sleep(0)
message = await websocket.recv()
print(message)
async def connect_to_dealer():
websocket = await websockets.connect(websocketadress)
hello_message = await websocket.recv()
print(hello_message)
async def my_app():
websocket = await connect_to_dealer()
asyncio.ensure_future(listen_for_message(websocket))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(my_app())
loop.run_forever()
And it raises the error:
File "\untitled0.py", line 71, in <module>
loop.run_forever()
File "\Anaconda3\lib\asyncio\base_events.py", line 525, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
And without the
import nest_asyncio
nest_asyncio.apply()
I get:
File "\untitled0.py", line 70, in <module>
loop.run_until_complete(my_app())
File "\Anaconda3\lib\asyncio\base_events.py", line 570, in run_until_complete
self.run_forever()
File "\Anaconda3\lib\asyncio\base_events.py", line 525, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
I still do not understand why it does this.
Upvotes: 3
Views: 18403
Reputation: 1122352
loop.run_until_complete()
already runs your loop 'forever'.
Instead of firing of your listen_for_message()
awaitable as a task, just await on it. That then runs forever, because listen_for_message()
itself never returns:
async def my_app():
websocket = await connect_to_dealer()
await listen_for_message(websocket)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(my_app())
Note that your connect_to_dealer()
function doesn't return the websocket; that's probably an oversight you want to correct:
async def connect_to_dealer():
return await websockets.connect(websocketadress)
I removed the hello_message = await websocket.recv()
/ print(hello_message)
lines there because listen_for_message()
will already receive messages and print them.
Upvotes: 4