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()