Why can't I use websocket in a function - python

When I try using websocket like this
ws = websocket.WebSocketApp(f"wss://fstream.binance.com/ws/{symbol}#aggTrade",on_message=on_message,on_close=on_close)
ws.run_forever()
it works fine but for some reason I want to use it like this
def func(symbol):
ws = websocket.WebSocketApp(f"wss://fstream.binance.com/ws/{symbol}#aggTrade",on_message=on_message,on_close=on_close)
ws.run_forever()
func("btcusdt")
but it's not working why can't I use websocket in func how can I do that

This (minor change to OP's code due to SSL issue) works perfectly on Python 3.9.9
import websocket
import ssl
def on_msg(_, msg):
print(msg)
def on_err(_, err):
print(err)
def func(symbol):
ws = websocket.WebSocketApp(
f"wss://fstream.binance.com/ws/{symbol}#aggTrade", on_message=on_msg, on_error=on_err)
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
if __name__ == '__main__':
func('btcusdt')

Related

Client-server implementaion using tornado_http2 api

I am trying to implement a client-server using tornado_http2 api in python but server never receive messages from the client.
I have checked that server is well started with this comm
and and I had this result:
(mmsx-TPjM8MGB-py3.9) xx#ITLP071: 7 (master) ~/dev/mmsx/tornado_http2/demo$ proxy=127.0.0.1:8443; curl --http2-prior-knowledge -d "bla bla" -X POST https://localhost:8443/ -E test.crt
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
And from the output server :
(mmsx-TPjM8MGB-py3.9) xx#ITLP071: 130 (master) ~/dev/mmsx/tornado_http2/demo$ poetry run python server_test.py
[I 220722 04:02:37 server_test:30] starting
[W 220722 04:02:41 iostream:1517] SSL Error on 7 ('127.0.0.1', 60040): [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:1123)
The connection is not perfectly done (that I do not succed to resolve for now) but at least I have a reaction from the server.
With request from the client, I have no response.
Please find my server code below:
import logging
import os
import ssl
from tornado.ioloop import IOLoop
from tornado.options import parse_command_line
from tornado.web import Application, RequestHandler
from tornado_http2.server import Server
class MainHandler(RequestHandler):
def get(self):
self.write("Hello world")
def post(self):
self.write("bla bla")
def main():
parse_command_line()
ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ssl_ctx.load_cert_chain(
os.path.join(os.path.dirname(__file__), 'test.crt'),
os.path.join(os.path.dirname(__file__), 'test.key'))
app = Application([('/hello', MainHandler)], debug=True)
server = Server(app, ssl_options=ssl_ctx)
port = 8443
address = "127.0.0.1"
server.listen(port, address)
logging.info("starting")
IOLoop.instance().start()
if __name__ == '__main__':
main()
And my client code:
from tornado_http2.curl import CurlAsyncHTTP2Client as HTTP2Client
import asyncio
URI = "http:127.0.0.1:8443/hello"
class Test():
def __init__(self):
self.__client = HTTP2Client(force_instance=True)
async def send(self):
global URI
body = "body"
response = await self.__client.fetch(URI, method='POST', body=body,
validate_cert=False)
print(response)
def main():
asyncio.run(Test().send())
if __name__ == "__main__":
main()
I started the server in a terminal and then the client in another one and for me, it should displayed in the client console the result of the request.
Thanks for your help !
OK, I have found.
It is a bug in tornado_http2 api. The event loop has to be created before the instanciation of the class HTTP2Client, else this does not work.
If the client code is remplaced bu this, it will work :
from tornado_http2.curl import CurlAsyncHTTP2Client as HTTP2Client
import asyncio
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
class Test():
def __init__(self):
self.__client = HTTP2Client(force_instance=True)
async def send(self):
uri = "https://127.0.0.1:8443/hello"
response = await self.__client.fetch(uri, validate_cert=False)
print(response.body.decode('utf-8'))
def run_asyncio():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(Test().send())
finally:
loop.close()
asyncio.set_event_loop(None)
def main():
run_asyncio()
if __name__ == "__main__":
main()
Hopefully it will help someone =).

How do I send keepalive requests with websocket-client?

I need to add some code to send keepalive request every 5 seconds to the following program which is using websocket-client
def on_open(wsapp):
wsapp.send(json.dumps(reqlogin))
wsapp.send(json.dumps(reqsub))
def on_message(wsapp, msg):
handle(msg)
wsapp = websocket.WebSocketApp(url, on_open=on_open, on_message=on_message)
wsapp.run_forever()
I've looked at documentation but couldn't find anything appropriate.
I managed to solve the issue using threading:
def on_open(wsapp):
wsapp.send(json.dumps(reqlogin))
wsapp.send(json.dumps(reqsub))
def on_message(wsapp, msg):
handle(msg)
wsapp = websocket.WebSocketApp(url, on_open=on_open, on_message=on_message)
wsappthread = threading.Thread(target=wsapp.run_forever,
daemon=True)
wsappthread.start()
while True:
time.sleep(5)
wsapp.send(json.dumps(reqkeepalive))

Code Not Printing In Async Python Websocket

I have been trying to build the following websocket using python:
import socket
import websockets
import asyncio
import traceback
# Find host name
HELLO_MY_NAME_IS = socket.gethostname()
print(HELLO_MY_NAME_IS)
# Find IP
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(('8.8.8.8', 53))
MY_IP = s.getsockname()[0]
print(MY_IP)
async def port_scan():
if not MY_IP[:3] == '192' and not MY_IP[:3] == '10.' and not MY_IP[:3] == '172':
print('This is not a private network! SHUTTING DOWN!')
exit()
ip_range = MY_IP.split('.')
ip_range.pop()
ip_range = '.'.join(ip_range)
print(ip_range)
async def register_client(websocket, _):
async for message in websocket:
print(message)
if __name__ == '__main__':
start_server = websockets.serve(register_client, MY_IP, 1111)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Everything seems to work fine and no errors come up. However, when I run the program, print(ip_range) does not show, which lies within 'async def port_scan()'. I think there is an issue with the code in this section. Does anyone have any idea what could be the problem and how to fix it?

Python websocket automatically closes with basic auth

I am attempting to setup a websocket using the websocket-client library using python 3.7. The documentation from the API provider states that basic auth is required.
Below is the code I am using to try subscribing to their test channel. The test channel should send responses back nonstop until we close the socket.
email = b'myemail#domain.com'
pw = b'mypassword'
_str = (base64.b64encode(email + b':' + pw)).decode('ascii')
headerValue = 'Authorization: Basic {0}'.format(_str)
def on_message(ws, msg):
global msg_received
print("Message received: ", msg)
msg_received += 1
if msg_received > 10:
ws.send(json.dumps({"unsubscribe": "/test"}))
ws.close()
def on_error(ws, error):
print("ERROR: ", error)
def on_close(ws):
print("Closing websocket...")
def on_open(ws):
print("Opening...")
ws.send(json.dumps({'subscribe': '/test'}))
time.sleep(1)
if __name__ == '__main__':
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://api-ws.myurl.com/",
header=[headerValue],
on_message=on_message,
on_error=on_error,
on_close=on_close))
ws.on_open = on_open
ws.run_forever()
When I run this, I am able to see my request headers, and their response headers which show that the connection was upgraded to a websocket and I am assigned a Sec-Websocket-Accept. Then, the websocket immediately closes without any responses coming through.
I have tried first sending a post request to the login api and generating a sessionID and csrftoken, and then passing those as cookies in the websocketapp object. It didn't work. I have tried passing the headers as an actual dict but that doesn't work either. I've tried way too many variations of the b64 encoding and none of them work.
Any advice would be appreciated.

Python Cyclic Dependency with Async I/O

While looking over the new features in Python 3.x, I was intrigued by the asyncio library being added. After looking at the reference documentation, I decided to play around with it a little bit.
This worked well until I tried to make it work for multiple clients, and keep a list of all active/connected clients. This introduced a cyclic dependency between the server class and the session class.
Now, I've tried a few different ways to resolve this; however, there doesn't appear to be any way for me to get at this data directly from the server class through any method/functional call.
While I have been able to workaround this by using a "lazy" import, it seems like this my be indicative of either a poor design, a lack of understanding of the library itself, or a combination of both.
Code wise, I have a small sample put together. Am I missing an obvious solution here, or does my organization need to change to better support the functionality provided by the asyncio library?
__main__.py:
from network.server import Server
def main(args=None):
s = Server()
try:
s.run()
except KeyboardInterrupt:
pass
s.close()
if __name__ == "__main__":
main()
server.py:
import asyncio
from network.session import Session
class Server:
sessionList = []
def __init__(self):
self.handler = None
self.loop = asyncio.get_event_loop()
self.coro = self.loop.create_server(Session, 'localhost', 1234)
def run(self):
self.handler = self.loop.run_until_complete(self.coro)
print('Server Running On: {}'.format(self.handler.sockets[0].getsockname()))
self.loop.run_forever()
def close(self):
self.handler.close()
self.loop.run_until_complete(self.handler.wait_closed())
self.loop.close()
#staticmethod
def add_session(session):
Server.sessionList.append(session)
#staticmethod
def del_session(session):
Server.sessionList.remove(session)
session.py:
import asyncio
class Session(asyncio.Protocol):
def __init__(self):
from network.server import Server
self._transport = None
Server.add_session(self)
def connection_made(self, transport):
self._transport = transport
self._transport.write('Echo Server Example\r\n\r\n'.encode())
def data_received(self, data):
self._transport.write(data)
def eof_received(self):
self._transport.close()
def connection_lost(self, exc):
from network.server import Server
Server.del_session(self)
if exc is not None:
self._transport.close()
You may pass server instance into Session constructor:
self.loop.create_server(lambda: Session(self), 'localhost', 1234)
Storing sessionList as global object is not the best practice.
I recommend saving it as self.sessionList = [] in Server.__init__ and converting both add_session and del_session from staticmethod into regular methods.

Categories