我尝试使用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
中表示“未解决的参考”#34;
答案 0 :(得分:7)
使用匿名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)
...
答案 1 :(得分:5)
WebSocketApp
需要用于其回调的可调用对象(包括您在构造函数中传递的对象,如on_message
,以及您在事后{i}重新设置的对象)。
普通函数是可调用对象,因此您的非OO版本可以正常工作,因为您正在传递普通函数。
绑定方法是也是可调用对象。但是你的OO版本并没有通过绑定方法。顾名思义,绑定方法绑定到对象。您可以使用on_open
表示法执行此操作。就你而言,那是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
之外的任何内容,那么该类就像一个命名空间。并不是说这总是一件坏事,但它通常表明你需要至少考虑一下你的设计。你需要保持任何状态吗?如果没有,为什么你想要一个班级?
您可能需要重新阅读tutorial section on Classes以了解方法,self
等。
答案 2 :(得分:1)
你需要添加" 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)
答案 3 :(得分:1)
Self将这些方法作为Class方法,让这个方法工作,因为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()
答案 4 :(得分:0)
我想尝试这种方式:
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
数目不匹配(类方法还有一个参数self
)。
我上面有一个handler
来处理消息,方法close(self)
用来清理一些资源,run_forever(self)
是用来运行websocket的。
答案 5 :(得分:0)
这有效:
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)
但是你无法进入自我
答案 6 :(得分:0)
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
参数。
读取错误日志。
_callback中的文件“ venv / lib / python3.7 / site-packages / websocket / _app.py”,第343行 回调(* 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)。请注意,它在self
中已经有自己的def _callback(self, callback, *args)
。
因此,每个CustomClient
实例的回调都不应具有ws参数。
答案 7 :(得分:0)
只需更新此页面上其他作者编写的代码,即可为我工作。 问题在于,在事件回调函数定义(例如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")