Home > database >  How to call Python Tornado Websocket Server inside another Python
How to call Python Tornado Websocket Server inside another Python

Time:01-03

I would like to implement Python Tornado Websocket Server inside another Python (main) and trigger send messages when needed. The main creates two threads. One of them is for Python Server and the other is for my loop that will trigger message.

When I start server from initial, server works fine however because its endless following main files doesn't run. So I start server inside a thread but this time I receive "RuntimeError: There is no current event loop in thread 'Thread-1 (start_server)'"

Main.py

import tornadoserver
import time
from threading import Lock, Thread

class Signal:
    def __init__(self):
        #self.socket = tornadoserver.initiate_server()
        print("start")

    def start_server(self):
        print("start Server")
        self.socket = tornadoserver.initiate_server()

    def brd(self):
        print("start Broad")
        i = 0
        while True:
            time.sleep(3)
            self.socket.send(i)
            i = i   1

    def job(self):
        # --------Main--------
        threads = []
        for func in [self.start_server, self.brd, ]:
            threads.append(Thread(target=func))
            threads[-1].start()

        for thread in threads:
            thread.join()

Signal().job()

tornadoserver.py

import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.websocket as ws
from tornado.options import define, options
import time

define('port', default=4041, help='port to listen on')
ws_clients = []


class web_socket_handler(ws.WebSocketHandler):

    @classmethod
    def route_urls(cls):
        return [(r'/', cls, {}), ]

    def simple_init(self):
        self.last = time.time()
        self.stop = False

    def open(self):

        self.simple_init()
        if self not in ws_clients:
            ws_clients.append(self)
            print("New client connected")
            self.write_message("You are connected")

    def on_message(self, message):
        if self in ws_clients:
            print("received message {}".format(message))
            self.write_message("You said {}".format(message))
            self.last = time.time()

    def on_close(self):
        if self in ws_clients:
            ws_clients.remove(self)
            print("connection is closed")
            self.loop.stop()

    def check_origin(self, origin):
        return True

    def send_message(self, message):
        self.write_message("You said {}".format(message))


def send(message):
    for c in ws_clients:
        c.write_message(message)


def initiate_server():
    # create a tornado application and provide the urls
    app = tornado.web.Application(web_socket_handler.route_urls())

    # setup the server
    server = tornado.httpserver.HTTPServer(app)
    server.listen(options.port)

    # start io/event loop
    tornado.ioloop.IOLoop.instance().start()

CodePudding user response:

Using Google I found tornado issue

Starting server in separate thread gives... RuntimeError: There is no current event loop in thread 'Thread-4' · Issue #2308 · tornadoweb/tornado

and it shows that it has to use

asyncio.set_event_loop(asyncio.new_event_loop())

to run event loop in new thread

Something like this

import asyncio

# ...

def initiate_server():

    asyncio.set_event_loop(asyncio.new_event_loop())  # <---

    # create a tornado application and provide the urls
    app = tornado.web.Application(web_socket_handler.route_urls())

    # setup the server
    server = tornado.httpserver.HTTPServer(app)
    server.listen(options.port)

    # start io/event loop
    tornado.ioloop.IOLoop.instance().start()
  • Related