Tornado-如何在另一个函数中调用处理程序
Posted
技术标签:
【中文标题】Tornado-如何在另一个函数中调用处理程序【英文标题】:Tornado- how to call a handler in another function 【发布时间】:2016-07-29 18:50:29 【问题描述】:我目前正在尝试使用 Tornado 的 web-socket 处理程序在每次调用某个函数时更新仪表板。这是处理程序:
class WebSocketHandler(websocket.WebSocketHandler):
clients = []
def open(self):
logging.info("WEBSOCKET OPEN")
WebSocketHandler.clients.append(self)
def on_message(self, message):
logging.info("message from websocket recieved")
self.write_message("WebSocket connected")
def on_close(self):
logging.info("WEBSOCKET closed")
这里是加载时连接 WebSocket 的客户端脚本:
function WebSocketTest()
var ws = 0;
ws = new WebSocket("ws://localhost:8008/WEB");
ws.onopen = function()
ws.send("initial connect")
ws.onmessage = function (evt)
console.log(evt.data)
;
ws.onclose = function()
console.log("closed ");
;
websockets 连接成功。
我需要从WebSocketHandler
调用write_message
,但我很困惑它的实例是什么?我一直遇到的错误是 self isn't defined
但我不确定 self 到底是什么?我知道,每当客户端尝试加载 ^/WEB$
时,WebSocketHandler
就会运行
编辑:这是我的server.py
文件,我需要在spawn callback
调用itercheckers
之后立即调用write_message
class Server():
@classmethod
def run(cls):
options.parse_command_line()
# Start web
template_path = os.path.join(os.path.dirname(__file__), 'templates')
jinja2loader = Jinja2Loader(template_path)
kwargs = dict(
template_loader=jinja2loader,
static_path=os.path.join(os.path.dirname(__file__), 'static'),
debug=True,
login_url="/auth/login",
cookie_secret="dn470h8yedWF9j61BJH2aY701i6UUexx"
)
app = web.Application(handlers, **kwargs).listen(
configuration['server']['port'],)
# Reset events
@gen.coroutine
def reset(parent=None):
if parent is None:
parent = configuration
# Reset event happyness
yield events.reset_happy(parent)
# Read last status
data = yield events.get(parent)
# Read and set happy from the last status
happy = (data or ).get('status', events.STATUS_OK) \
in events.HAPPY
yield events.set_happy(parent, happy)
# Iterate sub-events
for event in parent['events']:
yield reset(event)
ioloop.IOLoop.current().run_sync(reset)
# Start checkers
def itercheckers(parent):
index = 0
for event in parent.get('events', []):
if 'checker' in event:
checker = event['checker']
p, m = checker['class'].rsplit('.', 1)
ioloop.IOLoop.current().spawn_callback(
getattr(importlib.import_module(p), m)(
event=event,
frequency=checker.get('frequency', 1),
params=checker['params']
).run)
index += 1
itercheckers(event)
itercheckers(configuration)
# Start alerts
ioloop.IOLoop.current().run_sync(alerts.reset)
for alert in configuration['alerts']:
p, m = alert['class'].rsplit('.', 1)
ioloop.IOLoop.current().spawn_callback(
getattr(importlib.import_module(p), m)(
alert=alert
).run
)
# Start loop
ioloop.IOLoop.current().start()
【问题讨论】:
您如何访问它?你不去 ws://localhost:8000/ws 吗?您必须使用 js 制作 html 页面并在该页面上打开控制台以查看输出是什么 不,我愿意。访问 WebSocketHandler 的链接是“/WEB”。new WebSocket("ws://localhost:8008/WEB");
连接我
【参考方案1】:
首先,self
关键字指向当前正在处理的 websocket 客户端。要使用 tornado websockets,您必须初始化 tornado 应用程序
app = web.Application([
(r'/ws', WSHandler), #tells it to redirect ws:// to websocket handler
#Choose different names from defaults because of clarity
])
if __name__ == '__main__':
app.listen(5000) #listen on what port
ioloop.IOLoop.instance().start()
那么你必须有 WSHandler
类你将 websockets 流量指向
class WSHandler(websocket.WebSocketHandler):
#crossdomain connections allowed
def check_origin(self, origin):
return True
#when websocket connection is opened
def open(self):
print("Client connected ")
def on_close(self):
print("Client disconnected")
def on_message(self,message):
self.write_message(message) #echo back whatever client sent you
所以完整的应用看起来像
from tornado import websocket, web, ioloop
clients = []
#whenever you want to broadcast to all connected call this function
def broadcast_message(msg):
global clients
for client in clients:
client.write_message(msg)
class WSHandler(websocket.WebSocketHandler):
#crossdomain connections allowed
def check_origin(self, origin):
return True
#when websocket connection is opened
def open(self):
#here you can add clients to your client list if you want
clients.append(self)
print("Client connected ")
def on_close(self):
clients.remove(self)
print("Client disconnected")
def on_message(self,message):
self.write_message(message) #echo back whatever client sent you
app = web.Application([
(r'/ws', WSHandler), #tells it to redirect ws:// to websocket handler
#Choose different names from defaults because of clarity
])
if __name__ == '__main__':
app.listen(5000) #listen on what port
ioloop.IOLoop.instance().start()
现在用 js 连接到它
function WebSocketTest()
var ws = new WebSocket("ws://localhost:5000/ws");
ws.onopen = function()
ws.send("initial connect")
ws.onmessage = function (evt)
console.log(evt.data)
;
ws.onclose = function()
console.log("closed ");
;
我还没有测试过,但应该可以工作
【讨论】:
对不起,我应该包含它,但我有一个server.py
文件,我在其中创建 web.Application
并传递处理程序列表。我绝对可以将我的客户连接到服务器。我想弄清楚的是如何根据服务器端事件将数据从服务器发送到客户端。
您要发送给特定客户或所有客户
所有客户。这是一个状态仪表板,每当调用特定函数时我都需要更新它
好的,我马上编辑服务器代码......现在你只需调用广播消息,带有消息参数broadcast_message("ABC")
,它会将该消息发送到所有连接的客户端,但你可以调用它只有在它声明之后,因为 python 被解释它不能看到前面以上是关于Tornado-如何在另一个函数中调用处理程序的主要内容,如果未能解决你的问题,请参考以下文章
如何从 C++ 代码引发事件并在另一个进程的 C# 代码中调用处理程序?