Having two scripts publishing on the same port with zmq - zeromq

I would like to have two python scripts (it can be more in real use) that publishes on the same port to a single client. Here is the code for my scripts:
server1.py:
import time
import zmq
ctx = zmq.Context()
s1 = ctx.socket(zmq.PUB)
s1.connect("tcp://127.0.0.1:5566")
for i in range(10):
s1.send_pyobj({'job':'publisher 1','yo':10})
time.sleep(5)
server2.py:
import time
import zmq
ctx = zmq.Context()
s2 = ctx.socket(zmq.PUB)
s2.connect("tcp://127.0.0.1:5566")
for i in range(10):
s2.send_pyobj({'job':'publisher 2','yo':10})
time.sleep(5)
client.py:
import zmq
ctx = zmq.Context()
c = ctx.socket(zmq.SUB)
c.bind("tcp://127.0.0.1:5566")
c.setsockopt(zmq.SUBSCRIBE, '')
while True:
msg = c.recv_pyobj()
print("MSG: ", msg)
This naive implementation works but, being new to zmq,I was wondering if it was indeed the right implementation or if there was a better way to proceed.

I think that your design is valid. However, as the comments to the answer in this similar question suggest, you might struggle to subscribe with multiple clients with this architecture.

Related

How to add new thread for every new client in python websockets?

import asyncio
import websockets
import threading
async def server_handle(websocket,path):
print("Server is waiting!!!!")
while True:
msg = await websocket.recv()
print(f"Client : {msg}")
await websocket.send(input("Server : "))
def add_new_clients():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
start_server = websockets.serve(server_handle, "localhost", 1234)
loop.run_until_complete(start_server)
loop.run_forever()
loop.close()
total_clients = 0
if __name__ == "__main__":
# daemon server thread:
server = threading.Thread(target=add_new_clients, daemon=True)
server.start()
total_clients+=1
print(f"total clients : {total_clients}")
Here i am trying to add new thread to handle each clients request seperately using python websockets . for example if client1 connects to the server one thread should be created and sholud take care of the request and responce of that particular client. is there any way?.

Voila, jupyter and websockets: how to print?

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

Websocket with Locust, no error but no data

The fixed code (from https://medium.com/#rajatsaxena120/websockets-in-python-d91c7bc2fd22, https://stackoverflow.com/questions/ask?newreg=520c9b343e534667aa88f67ea3f79cb4) seems to work:
import time, websocket
from locust import HttpUser, task, between, events
from websocket import create_connection
import gevent
class QuickstartUser(HttpUser):
wait_time = between(1, 5)
#task
def on_start(self):
ws = create_connection('wss://REDACTED.com')
g = gevent.spawn(self.connect)
g.get(block=True, timeout=10)
g = gevent.spawn(self.subscribe)
g.get(block=True, timeout=10)
g = gevent.spawn(self.send)
g.get(block=True, timeout=10)
def _receive():
ws = create_connection('wss://REDACTED.com')
while True:
res = ws.recv()
events.request_success.fire(
request_type='Websocket Receive Message',
name='test websocket message receive',
response_time=0,
response_length=len(res)
)
gevent.spawn(_receive)
But when running tests, nothing happen, no connection to websocket, no load on the server.
What am I missing?

Latency is not identified

I was testing my code today, when suddenly an error came up saying that they could not find a reference of latency in _ _ init.py _ _. This never happened before so I don't know what to do. Here is the code of the command and the imports:
import discord
from discord.ext import commands
from pretty_help import PrettyHelp
bot = commands.Bot(command_prefix=".")
bot.load_extension('cog_admin')
bot.load_extension('cog_stuff')
bot.load_extension('cog_info')
bot.help_command = PrettyHelp()
bot.help_command = PrettyHelp(index_title="CatsyBot Help Page", no_category="Stuff")
#commands.command()
async def ping(ctx):
"""PING PONG"""
await ctx.send(f"🏓 Pong with {str(round(commands.latency, 2))}")
commands doesn't have the attribute latency, but your bot instance has
await ctx.send(f"🏓 Pong with {str(round(bot.latency, 2))}")

how can i use async/await to call Future obj in python3.6

I have doubts about Python's await and hava an example,it tries to use await to fetch results from the future obj.
import time
import asyncio
import time
import random
import threading
db = {
"yzh": "pig",
"zhh": "big pig"
}
loop = asyncio.get_event_loop()
def _get_redis(username, clb):
def foo():
data = db[username]
time.sleep(0.1)
print("start clb")
clb(data)
t1 = threading.Thread(target=foo)
t1.start()
def get_redis(username):
print("start get redis")
myfuture = asyncio.Future()
def clb(result):
print("clb call")
myfuture.set_result(result)
_get_redis(username, clb)
return myfuture
async def main():
print("start main")
data = await get_redis("yzh")
print("data is {}".format(data))
loop.run_until_complete(asyncio.ensure_future(main()))
loop.close()
and i got output without future's result:
start main
start get redis
start clb
clb call
How should i use await to get the future's result?I tried many times. Thanks for your help.
As you said in your comment, you're supposed to use loop.call_soon_threadsafe when running an asyncio callback from a thread:
loop.call_soon_threadsafe(myfuture.set_result, result)
However, a better approach for calling a synchronous function from asyncio is to use loop.run_in_executor:
def _get_redis(username):
time.sleep(0.1)
return db[username]
async def get_redis(username):
return await loop.run_in_executor(None, _get_redis, username)
This way, you won't have to deal with futures and thread-safe callbacks.

Resources