Below is an example of a websocket that uses threads to maintain a web socket connection.
import websocket
import threading
from time import sleep
def on_message(ws, message):
print message
def on_close(ws):
print "### closed ###"
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_close = on_close)
wst = threading.Thread(target=ws.run_forever)
wst.daemon = True
wst.start()
conn_timeout = 5
while not ws.sock.connected and conn_timeout:
sleep(1)
conn_timeout -= 1
msg_counter = 0
while ws.sock.connected:
ws.send('Hello world %d'%msg_counter)
sleep(1)
msg_counter += 1
I'm wondering, how can I modify this code to use a Process instead? Threads aren't parallel due to the GIL and I want to speed up this code. I've tried converting this code myself, however, my main issue is how to pass data from the socket process to the main process.
Does anyone know how to convert this code? I'm having difficulties.
Related
I have a WebSocket I run generally as follows:
import websocket
def on_message(ws, message):
...
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message,
on_close=on_close)
ws.run_forever(ping_interval=5, ping_timeout=-1)
I want this to run but also perform another check from a function on every minute that elapses. Is there any way I can do this. I have heard of maybe threading or asyncio but have never used either. Any advice would be greatly appreciated.
The simplest approach would be using threading
import websocket
import threading
def runs_every_minute():
while True:
# do something
time.sleep(60)
def on_message(ws, message):
...
t = threading.Thread(target=runs_every_minute)
t.start() # starts the thread
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message,
on_close=on_close)
ws.run_forever(ping_interval=5, ping_timeout=-1)
While using websocket client to send test messages to a django server, I cannot get a script to work which can both send and receive messages.
The following python script is what I have attempted:
import websocket
import threading
import json
from time import sleep
# handle message event
def on_message(ws, message):
print("message recieved: %s" % message)
# handle close event
def on_close(ws):
print("channel closed")
# execute as main script
if __name__ == "__main__":
websocket.enableTrace(True)
# new app object connecting to headstation
ws = websocket.WebSocketApp("ws://192.168.0.106:8000/?testI123", on_message = on_message, on_close = on_close)
# run in a new thread - kill if script ends
ws_listener = threading.Thread(target=ws.run_forever())
ws_listener.daemon = True
# start second thread
ws_listener.start()
# attempt connection 5 times
timeout = 5
while not ws.sock.connected and timeout:
sleep(1)
timeout -= 1
# error on timeout
if (timeout == 0):
print("Connection to server timed out")
print("test 1")
# periodically send test message to server
message_num = 0
while ws.sock.connected:
# send node id and message
message = 'hello %d'%message_num
ws.send(message)
sleep(1)
message_num += 1
This connections successfully, indicted by the server, and receives messages sent from the server, but does not send anything.
Periodically, something like this is displayed on the terminal:
send: b'\x8a\x84\xe2\xe9\xa8\xe2\x8f\xdc\xe2\x84'
If I simply use
ws = websocket.WebSocket()
ws.connect(url)
ws.send("hello")
then this works perfectly. Suggesting it is something wrong with my little python script displayed above.
Found the problem, stupid mistake of course:
ws_listener = threading.Thread(target=ws.run_forever())
should be:
ws_listener = threading.Thread(target=ws.run_forever)
without parentheses.
First one passes result of ws.run_forever to the target, second one sets ws.run_forever as the target, which was the intended outcome.
Let's say I want to create a chat-like application. A client can send text to the server and vice versa. The order of text exchanges can be arbitrary.
The server depends on another stream which controls the server response stream.
The GRPC stream is exposed as a python generator. How can the server now wait for client input and input on the other stream at the same time? Normally one would use something like select(), but here we have generators.
I have some example code which implements the wanted behavior but requires an additional thread on the client and server side. How can I achieve the same result without a thread?
Proto:
syntax = 'proto3';
service Scenario {
rpc Chat(stream DPong) returns (stream DPong) {}
}
message DPong {
string name = 1;
}
Server:
import random
import string
import threading
import grpc
import scenario_pb2_grpc
import scenario_pb2
import time
from concurrent import futures
class Scenario(scenario_pb2_grpc.ScenarioServicer):
def Chat(self, request_iterator, context):
def stream():
while 1:
time.sleep(1)
yield random.choice(string.ascii_letters)
output_stream = stream()
def read_incoming():
while 1:
received = next(request_iterator)
print('received: {}'.format(received))
thread = threading.Thread(target=read_incoming)
thread.daemon = True
thread.start()
while 1:
yield scenario_pb2.DPong(name=next(output_stream))
if __name__ == '__main__':
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
scenario_pb2.add_ScenarioServicer_to_server(
Scenario(), server)
server.add_insecure_port('[::]:50052')
server.start()
print('listening ...')
while 1:
time.sleep(1)
Client
import threading
import grpc
import time
import scenario_pb2_grpc, scenario_pb2
def run():
channel = grpc.insecure_channel('localhost:50052')
stub = scenario_pb2_grpc.ScenarioStub(channel)
print('client connected')
def stream():
while 1:
yield scenario_pb2.DPong(name=input('$ '))
input_stream = stub.Chat(stream())
def read_incoming():
while 1:
print('received: {}'.format(next(input_stream).name))
thread = threading.Thread(target=read_incoming)
thread.daemon = True
thread.start()
while 1:
time.sleep(1)
if __name__ == '__main__':
print('client starting ...')
run()
It is not currently possible to do this without spending the threads that you're spending. We're thinking about implementing enhancements that would allow implementations to avoid taking another thread, but those would be months away at earliest.
Main.py:
def thread(i):
while True:
try:
lock.acquire()
if shared_var == 0:
Client.f1()
shared_var +=1
if shared_var == 2:
Client.f2()
time.sleep(DELAY)
shared_var += 1
if shared_var == 3:
time.sleep(5)
Client.f3()
Client.f4()
shared_var += 1
finally:
lock.release()
if __name__ == '__main__':
thread1 = threading.Thread(target=thread, args=(0,))
thread1.start()
Client.py:
def socket():
def f1():#send function
def f2():#recv function.
def f3():
def f4():
def f5():
I have non blocking socket at client side.
I have thread in main file which calls this functions
at client side. I have a function(lets say f2) which will be receiving some data through socket. I will be sending series of commands through socket and will be getting response in function f2.
Let say my function f3 is sync function which monitor the server notifies me if any state changes occurs in server.
Problem:
Since am getting multiple response from server i want to catch specifically catch the state changes response form server. Is it possible?
Note : Am using a generic function for send and recv which means all functions sends the commands and recv the response via f1 and f2.
Ps am a newbie to python
I am wanting to run a program in Python that sends a message every second via web sockets to a Tornado server. I have been using the example on websocket-client;
This example does not work, because ws.run_forever() will stop the execution of the while loop.
Can somebody give me an example of how to correctly implement this as a threaded class which I can both call the send method of, but also receive messages?
import websocket
import thread
import time
def on_message(ws, message):
print message
def on_error(ws, error):
print error
def on_close(ws):
print "### closed ###"
def on_open(ws):
pass
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_error = on_error, on_close = on_close)
ws.on_open = on_open
ws.run_forever()
while True:
#do other actions here... collect data etc.
for i in range(100):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(1)
There's an example in their github page that does exactly that. It seems like you started out of that example and took the code that sends messages every second out of the on_open and pasted it after the run_forever call, that BTW runs until the socket is disconnected.
Maybe you are having issues with the basic concepts here. There's always going to be a thread dedicated to listening to the socket (in this case the main thread that enters a loop inside the run_forever waiting for messages). If you want to have some other thing going on you'll need another thread.
Below is a different version of their example code, where instead of using the main thread as the "socket listener", another thread is created and the run_forever runs there. I see it as a bit more complicated since you have to write code to assure the socket has connected while you could use the on_open callback, but maybe it will help you understand.
import websocket
import threading
from time import sleep
def on_message(ws, message):
print message
def on_close(ws):
print "### closed ###"
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://echo.websocket.org/", on_message = on_message, on_close = on_close)
wst = threading.Thread(target=ws.run_forever)
wst.daemon = True
wst.start()
conn_timeout = 5
while not ws.sock.connected and conn_timeout:
sleep(1)
conn_timeout -= 1
msg_counter = 0
while ws.sock.connected:
ws.send('Hello world %d'%msg_counter)
sleep(1)
msg_counter += 1
In 2023, they have an updated example for dispatching multiple WebSocketApps using an asynchronous dispatcher like rel.
import websocket, rel
addr = "wss://api.gemini.com/v1/marketdata/%s"
for symbol in ["BTCUSD", "ETHUSD", "ETHBTC"]:
ws = websocket.WebSocketApp(addr % (symbol,), on_message=lambda w, m : print(m))
ws.run_forever(dispatcher=rel, reconnect=3)
rel.signal(2, rel.abort) # Keyboard Interrupt
rel.dispatch()
Hope it helps!