2

I want to start websocket server in separate thread. I have tried to implement as below but getting Runtime error as it says attached to different loop

Code:

#!/usr/bin/env python

# WS server example

import asyncio
import websockets
import threading
import time

async def hello(websocket, path):
    name = await websocket.recv()
    print(name)

    greeting = "Hello " + name +"!"

    await websocket.send(greeting)
    print(greeting)

start_server = websockets.serve(hello, "localhost", 8765)
eventLoop = asyncio.new_event_loop()
time.sleep(2)

def startWebSocket(loop, server):
    print("WS: thread started")
    asyncio.set_event_loop(eventLoop)
    asyncio.get_event_loop().run_until_complete(start_server)
    eventLoop.run_forever()

print("Run web socket in threaded env")
TH = threading.Thread(target=startWebSocket, args=[eventLoop, start_server,])
TH.start()

# then do some other work after this

Output:

Run web socket in threaded env
WS: thread started
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "threadWithWs.py", line 26, in startWebSocket
    asyncio.get_event_loop().run_until_complete(start_server)
  File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "/usr/lib/python3.5/asyncio/tasks.py", line 564, in _wrap_awaitable
    return (yield from awaitable.__await__())
  File "/home/krunal/.local/lib/python3.5/site-packages/websockets/py35/server.py", line 13, in __await_impl__
    server = await self._creating_server
  File "/usr/lib/python3.5/asyncio/base_events.py", line 923, in create_server
    infos = yield from tasks.gather(*fs, loop=self)
  File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
    yield self  # This tells Task to wait for completion.
RuntimeError: Task <Task pending coro=<_wrap_awaitable() running at /usr/lib/python3.5/asyncio/tasks.py:564> cb=[_run_until_complete_cb() at /usr/lib/python3.5/asyncio/base_events.py:164]> got Future <_GatheringFuture pending> attached to a different loop

Code exists with this error.

How to setup loop for websocket to start websocket server in thread?

I have followed this answer but no luck.

2
  • hello, any feedback please? Commented May 7, 2021 at 15:23
  • Actually, your solution didn't worked for me, So ended up using different library of websocket Commented May 8, 2021 at 15:36

1 Answer 1

1

You don't have to use threads with asyncio. It's redundant.

Do something like this (I actually don't know what websocket is, I assume start_server is a coroutine \ an awaitable). Create another async function, deputed to keep the loop alive. Before going into a while loop, spawn your task.

You may want to add an health check, using a global variable or wrapping all into a class.

async def run():
   eventLoop.create_task(start_server())
   while 1:
      # if not health_check():
      #     exit()
      await asyncio.sleep(1)

eventLoop.run_until_complete(run())

Do the other stuff by spawning more tasks.

To run blocking code into an asyncio loop, use eventLoop.run_in_executor(None, blocking_code): it's basically a friendly interface to threads.

As with threads, you live into the GIL.

Embrace the way asyncio do things.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.