2

Although the question might seem simple I can't see to find a viable way or anyway of printing the incoming messages from a threaded websocket.

Basically, I've created a jupyterlab notebook that lets me connect to a local websocket server and echo messages sent from a firecamp websocket connection. When running it on a cell (without the run button and run A.start()) I can see the prints but as soon as I hit the run button after restarting the kernal I can't see incoming messages.

Normally I would expect something like:

Function started
Someone said: test 1
Someone said: test 2

In the prints but nothing seems to apperas when hitting the run button.

The main objective is to be able to run the notebook with voila to upload to heroku but I can“t seem to make the prints work. If anybody has a clue or a better idea, I'm all ears.

Thanks in advance.

PD: Code

import ipywidgets as widgets
from IPython.display import Javascript, display
import websocket
import asyncio
import nest_asyncio
import threading
import websocket
import time
import sys
import trace
import logging
from time import sleep

output_box = widgets.Output()
class KThread(threading.Thread):
    """A subclass of threading.Thread, with a kill() method."""  
    def __init__(self, *args, **keywords):
        threading.Thread.__init__(self, *args, **keywords)
        self.killed = False

    def start(self):        
        """Start the thread."""
        self.__run_backup = self.run
        self.run = self.__run     
        threading.Thread.start(self)

    def __run(self):
        """Hacked run function, which installs the trace."""
        sys.settrace(self.globaltrace)
        self.__run_backup()
        self.run = self.__run_backup

    def globaltrace(self, frame, why, arg):
        if why == 'call':
          return self.localtrace
        else:
          return None

    def localtrace(self, frame, why, arg):
        if self.killed:
          if why == 'line':
            raise SystemExit()
        return self.localtrace

    def kill(self):
        ws.close()
        self.killed = True
def on_message(ws, message):    
    print(message)
def on_open(ws):
    ws.send("Connected Test")
def on_close(ws, close_status_code, close_msg):
    print("### closed ###")
def on_error(ws, error):
    print(error)
#This illustrates running a function in a separate thread. The thread is killed before the function finishes.
def func():    
    print('Function started')
    ws.run_forever()

ws = websocket.WebSocketApp("ws://localhost:7890", on_open=on_open,on_message = on_message, on_close = on_close,on_error = on_error)
A = KThread(target=func)

websocket.enableTrace(True)
run_button = widgets.Button(
    description='Run Button',
    disabled=False,
    button_style='info', # 'success', 'info', 'warning', 'danger' or ''
    tooltip='Run button function',
    icon='play'
)

def on_run_button_clicked(b):
    with output_box:
        A.start()       
run_button.on_click(on_run_button_clicked)
display(run_button,output_box)

This is the websocket server:

# Importing the relevant libraries
import websockets
import asyncio

# Server data
PORT = 7890
print("Server listening on Port " + str(PORT))

# A set of connected ws clients
connected = set()

# The main behavior function for this server
async def echo(websocket, path):
    print("A client just connected")
    # Store a copy of the connected client
    print(websocket)
    connected.add(websocket)
    # Handle incoming messages
    try:
        async for message in websocket:
            print("Received message from client: " + message)
            # Send a response to all connected clients except sender
            for conn in connected:                
                if conn != websocket:
                    await conn.send("Someone said: " + message)
    # Handle disconnecting clients 
    except websockets.exceptions.ConnectionClosed as e:
        print("A client just disconnected")
    finally:
        connected.remove(websocket)

# Start the server
start_server = websockets.serve(echo, "localhost", PORT)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Robon Rus
  • 21
  • 1

0 Answers0