[英]Using a websocket client as a class in python
我正在嘗試使用 websockets 訪問一些數據,但我無法真正繞過 websockets 文檔中給出的示例。
我有這個代碼( https://pypi.org/project/websocket_client/ )並想將它轉換成一個類。
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):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(1)
ws.close()
print "thread terminating..."
thread.start_new_thread(run, ())
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()
這個想法是在一個類中擁有所有這些 websocket 功能,這樣我就可以創建該類的一個對象。
我試圖開始這樣做,但我什至無法通過這個:
class MySocket(object):
def __init__(self):
websocket.enableTrace(True)
self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
on_message = on_message,
on_error = on_error,
on_close = on_close)
def on_message(ws, message):
print message
def on_error(ws, error):
print error
def on_close(ws):
print "### closed ###"
def on_open(ws):
ws.send("Hello %d" % i)
錯誤立即在on_message
開始,說這是一個“未解析的引用”。
將調用打包在匿名lambda
函數中,以使用正確的self
實現正確調用:
class Client:
def __init__(self, db, symbols):
self.ws = websocket.WebSocketApp("wss://the.server.com/api",
on_message = lambda ws,msg: self.on_message(ws, msg),
on_error = lambda ws,msg: self.on_error(ws, msg),
on_close = lambda ws: self.on_close(ws),
on_open = lambda ws: self.on_open(ws))
def on_message(self, ws, message):
msg = json.loads(message)
print(msg)
...
WebSocketApp
的回調需要可調用對象(您在構造函數中傳遞的對象,如on_message
,以及事后設置的對象, on_open
)。
普通函數是可調用對象,因此您的非 OO 版本可以正常工作,因為您正在傳遞普通函數。
綁定方法也是可調用對象。 但是您的 OO 版本沒有傳遞綁定方法。 綁定方法,顧名思義,綁定到一個對象。 您可以使用obj.method
表示法來完成此操作。 在你的情況下,那是self.on_message
:
self.ws = websocket.WebSocketApp("ws://echo.websocket.org/",
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close)
self.ws.on_open = self.on_open
但是,您還有另一個問題。 雖然這會使您的錯誤消失,但不會使您的代碼真正工作。 一個普通的方法必須將self
作為它的第一個參數:
def on_message(self, ws, message):
print message
另外值得一提的是,你沒有真正使用類的東西。 如果您從不訪問self
任何內容,則該類就像一個命名空間。 並不是說這總是一件壞事,但這通常表明您至少需要仔細考慮您的設計。 真的有任何需要維護的狀態嗎? 如果沒有,你為什么首先要上課?
import websocket
try:
import thread
except ImportError:
import _thread as thread
import time
class OnyxGenericClient:
"""
Onyx Client Interface
"""
def __init__(self, ):
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://localhost:3000/",
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close)
self.ws = ws
self.ws.on_open = self.on_open
self.ws.run_forever()
# def initiate(self):
def on_message(self, message):
print(message)
return message
def on_error(self, error):
return error
def on_close(self):
print("### closed ###")
def run(self, *args):
global driver
driver = True
while driver:
try:
time.sleep(1)
print("Say something nice")
p = input()
self.ws.send(p)
except KeyboardInterrupt:
driver = False
time.sleep(1)
self.ws.close()
print("thread terminating...")
def on_open(self):
thread.start_new_thread(self.run, ())
if __name__ == "__main__":
websocket.enableTrace(True)
onyx_client = OnyxGenericClient()
不知道為什么大家還在放ws
參數。
閱讀錯誤日志。
文件“venv/lib/python3.7/site-packages/websocket/_app.py”,第 343 行,在 _callback 回調(*args)中
def _callback(self, callback, *args):
if callback:
try:
if inspect.ismethod(callback):
callback(*args)
else:
callback(self, *args)
except Exception as e:
_logging.error("error from callback {}: {}".format(callback, e))
if _logging.isEnabledForDebug():
_, _, tb = sys.exc_info()
traceback.print_tb(tb)
查看我們的回調, on_open(self, ws)
當try
塊執行時,它會檢查我們的回調是一個方法還是一個函數。 如果它是一個方法,它將執行callback(*args)
已經我們的自定義客戶端中的CustomClient
已經作為參數傳遞給 (*args)。 請注意,它已經在def _callback(self, callback, *args)
擁有自己的self
。 因此,作為CustomClient
實例的每個回調CustomClient
應該有 ws 參數。
您需要在類方法中添加“self”:
class MySocket(object):
def __init__(self):
websocket.enableTrace(True)
self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close)
def on_message(self, ws, message):
print message
def on_error(self, ws, error):
print error
def on_close(self, ws):
print "### closed ###"
def on_open(self, ws):
ws.send("Hello %d" % i)
Self 將這些方法作為類方法,得到這個作為 on_error/message/close 方法簽名將得到滿足,如果由 self 調用將引用類本身。
class MySocket(object):
def __init__(self,x):
websocket.enableTrace(True)
## Only Keep the object Initialisation here
self.x=x
self.ws=None
# call This method from a Object and it will create and run the websocket
def ws_comm(self):
self.ws = websocket.WebSocketApp(self.WS_URL,on_message =
self.on_message,on_error =self.on_error,on_close = self.on_close)
self.ws.on_open = self.on_open
self.ws.run_forever()
def on_error(self,ws, error):
print "onError", error
def on_close(self,ws):
print "onClosed"
#Send some message on open
def on_open(self,ws):
self.ws.send(json.dumps(register_msg))
def on_message(self,ws, msg):
self.ws.send(json.dumps(msg))
user1=Userapp('x')
user1.ws_comm()
只需更新此頁面上其他作者編寫的代碼,這對我有用。 問題是在像 on_message 這樣的事件回調函數定義中,我們不應該使用 ws 作為參數。 self 負責它,在這些事件處理函數的主體中,我們應該使用 self.ws
class MySocket(object):
def __init__(self):
websocket.enableTrace(True)
self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close)
def on_message(self, message):
# if you want to send something use like this
# self.ws.send()
print message
def on_error(self, error):
print error
def on_close(self):
print "### closed ###"
def on_open(self):
self.ws.send("Hello Message")
我想試試這種方式:
class FooClient(object):
def __init__(self):
def on_message(ws, message):
print message
# use 'self' variable to access other resource
# handle message from websocket server like this
self.handler.handle(message)
def on_error(ws, error):
print error
def on_close(ws):
print "### closed ###"
def on_open(ws):
ws.send("Hello %d" % i)
# assign to 'self.handler'
self.handler = FooHandler()
# maybe there are another module should be initiated
# ...
websocket.enableTrace(True)
self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
on_message = on_message,
on_error = on_error,
on_close = on_close)
def run_forever(self):
self.ws.run_forever()
def close(self):
"""clean other resources"""
pass
在方法__init__(self)
使用內部函數可以避免on_message(self, ws, message)
方法的參數數量與WebSocketApp
提供給其參數on_message
的數量不匹配的on_message
(類方法多了一個參數self
)。
我上面有一個handler
來處理消息,如果有的話,方法close(self)
來清理一些資源, run_forever(self)
來運行 websocket。
這是有效的:
class MySocket(object):
def __init__(self):
websocket.enableTrace(True)
self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close)
@staticmethod
def on_message(ws, message):
print message
@staticmethod
def on_error(ws, error):
print error
@staticmethod
def on_close(ws):
print "### closed ###"
@staticmethod
def on_open(ws):
ws.send("Hello %d" % i)
但你無權訪問 self
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.