I'm trying to wrap my head around the usage of websocket. Here's my code:
import websocket
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws):
print('Websocket: closed')
def on_open(ws):
print('Websocket: open')
ws = websocket.WebSocketApp('ws://echo.websocket.org/',
on_message = on_message,
on_error = on_error,
on_close = on_close,
on_open = on_open)
ws.run_forever()
First, why would I put
ws.on_open = on_open
instead of passing it while defining ws? (As I did in the code)
Moreoever, how can I send a message? I could include
ws.send(json.dumps("Hello")) under
def on_open(ws), is there some other way?
Finally, I'm not able to close the connection given that ws.run_forever() never stops, how can I do it? I tried to include ws.close() under def on_open(ws) but then I don't receive any message.
What I'm trying to get is how I can transpose this:
ws = ws.create_connection('ws://echo.websocket.org/')
ws.send(json.dumps("Hello"))
result = json.loads(ws.recv())
print(result)
using WebSocketApp, that is having the messages pushed printed directly, without having to request the result.
Related
I am using a third party API that provides websocket functionality for continuous stream of messages.
I want to use variables that are defined out of the on_message() function. The structure of the code is as below:
soc = WebSocket()
Live_Data = {}
Prev_Data = {}
def on_message(ws, message):
if <check condition about Prev_Data>:
<Do something on Prev_Data and Live_Data>
def on_open(ws):
print("on open")
def on_error(ws, error):
print(error)
def on_close(ws):
print("Close")
# Assign the callbacks.
soc._on_open = on_open
soc._on_message = on_message
soc._on_error = on_error
soc._on_close = on_close
soc.connect()
But when I run this, it throws error that
Prev_data is referenced before it is assigned
I think this is because the on_message() method is asynchronous and the next on_message() method tries to access the Prev_Data before the first on_message() has finished writing it.
So what is the mechanism to synchronously access the Prev_Data and some other such variables here?
P.S: When I don't use the Prev_Data at all, the code runs fine.
I have this...
import websocket
SOCKET = "wss://stream.binance.com:9443/ws/ADABUSB#nav_kline_1m"
def on_open(ws):
print('opened connection')
def on_close(ws):
print('close connection')
def on_message(ws, message):
print('received message')
print(message)
ws = websocket.WebSocketApp(SOCKET, on_open = on_open, on_close = on_close, on_message = on_message)
ws.run_forever()
When I run it it sticks on OPENED CONNECTION and then does nothing??
Any ideas?
No error messages and I have left it for minutes!!
Cheers
Zak
No error messages
How do you know, you haven't defined the on_error-callback :) ?
Try adding it like below and see if it makes a difference (it does on my end):
import websocket
SOCKET = "wss://stream.binance.com:9443/ws/ADABUSB#nav_kline_1m"
def on_open(ws):
print('opened connection')
def on_close(ws):
print('close connection')
def on_message(ws, message):
print('received message')
print(message)
def on_error(ws, message):
print('error:', message)
ws = websocket.WebSocketApp(SOCKET, on_open = on_open, on_close = on_close, on_message = on_message, on_error = on_error)
ws.run_forever()
Found this and it worked!
I am on a Mac...
Spot on! removed ::1 from /etc/hosts and its connecting. localhost was resolving to ::1. Thanks for help.
I'm currently using the websocket-client library to connect to a websocket by following the example code:
def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send('{ "event": "subscribe", "channel": "sensor"+i }')
time.sleep(1)
thread.start_new_thread(run, ())
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()
however if I try to send additional message to the websocket on-demand (say subscribe additional channels,
ws.send('{ "event": "subscribe", "channel": "sensor5" }')
How would I be able to achieve such? As the ws.run_forever() is already running, how can I get hold of the running websocket instance to submit the message?
It's more of a listener than the sender, for sending you can use this:
from websocket import create_connection
ws = create_connection("ws://echo.websocket.org/")
print("Sending 'Hello, World'...")
ws.send("Hello, World")
For Listener in your question snippet, you had on_message
Of whose implementation you can do:
def on_message(ws, message):
print(message) #do something with the message
I have set up websocket connections to multiple cryptocurrency exchanges but I'm having difficulty connecting to bitFlyer's.
My code is as follows:
import websocket
import json
def on_message(ws, message):
msg = json.loads(message)
print(msg)
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
ws.send(json.dumps({"method":"subscribe", "channel":"lightning_executions_FX_BTC_JPY"}))
while True:
if __name__ == "__main__":
#websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://ws.lightstream.bitflyer.com/json-rpc",
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.on_open = on_open
ws.run_forever()
I have tried many many variations of my on_open() message and most result in a ### closed ###
Invalid close opcode. error.
Unfortunately their documentation does not contain a Python sample located HERE.
Any help in sending the correct message is much appreciated.
I believe the format of message you sent was wrong, check the following reference from https://lightning.bitflyer.jp/docs/playgroundrealtime, guess it will solve.
# pip install websocket-client
import websocket
import json
CHANNEL = "lightning_board_snapshot_<productCode>"
def on_message(ws, message):
message = json.loads(message)
if message["method"] == "channelMessage":
print("{} {}".format(message["params"]["channel"], message["params"]["message"]))
def on_open(ws):
ws.send(json.dumps({"method": "subscribe", "params": {"channel": CHANNEL}}))
if __name__ == "__main__":
// note: reconnection handling needed.
ws = websocket.WebSocketApp("wss://ws.lightstream.bitflyer.com/json-rpc",
on_message = on_message, on_open = on_open)
ws.run_forever()
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!