我正在尝试在龙卷风中编写一个简单的推送引擎。基本上,我有一个程序在我的服务器上运行,不断生成一个输出,我通过 Python 处理该输出以更新字典,并且我希望将该字典发布到 Web 客户端,例如每分钟发布一次。
如果您的答案包含文档链接或重新表述我自己的问题,我将不胜感激。我正在阅读大量痛苦的龙卷风文档,因此任何帮助将不胜感激。
这是代码的框架,其中有注释解释我想要做什么:
import subprocess
import sys
import pprint
import tornado.ioloop
import tornado.web
# this is to run my bash process and continuously yiled its output
def runProcess(cmd):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
while True:
retcode = p.poll()
line = p.stdout.readline()
yield line
if retcode is not None:
break
class MainHandler(tornado.web.RequestHandler):
def get(self):
#What can I do here if I want to send the update data every minute?
self.write(data)
def get_data(self):
data = dict()
cmd = 'myProg --args'
# this program will produce a continuous stream of data
for line in runProcess(cmd.split()):
data[line.split()[0] = line.plit()[1]
#now dictionary is updated? yield result?
# even if I want to publish updates every minute?
yield all_data
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Run Code Online (Sandbox Code Playgroud)
如果您的客户端是网络浏览器,这听起来很适合websockets。
下面你会发现一个非常非常简单的例子。您应该添加额外的检查,如连接来源的实际验证、网络套接字关闭时的错误处理(这可能会发生......非常非常频繁)
1) Tornado服务器(文件stack_073.py):
import datetime
import time
import tornado.ioloop
import tornado.web
import tornado.websocket
def get_data():
return {
"current_time": datetime.datetime.strftime(
datetime.datetime.now(), "%Y-%m-%d %H:%M:%S"
)
}
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True
def open(self):
print("WebSocket opened")
while True:
data = get_data()
self.write_message(data)
time.sleep(1)
def make_app():
return tornado.web.Application([
(r"/websocket", WebSocketHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Run Code Online (Sandbox Code Playgroud)
现在,连接到 websocket 并接收推送的 HTML (+Javascript):
2)网络客户端(文件stack_073.html):
<html>
<header>
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onmessage = function (evt) {
var current_time_str = JSON.parse(evt.data)['current_time'];
document.getElementById("date").innerHTML = current_time_str;
};
</script>
</header>
<body>
<p id="date"></p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
如果您在终端上启动 Tornado 服务器,然后打开文件stack_073.html,您应该会看到时间每秒更新一次。正如您所看到的,没有 Javascript 计时器或任何东西(更新来自write_messageTornado 执行的)
这基本上会创建一个从浏览器到服务器的永久挂起的请求,服务器可以使用该请求将数据推送到浏览器:
编辑01(根据OP对此答案的评论):
如果 get_data 是一个应该在第一次连接时调用一次的函数,然后永远运行 [ 。。。] 用yield语句替换return语句可以解决这个问题吗?
差不多,是的。就是在这种情况下,您get_data返回一个生成器,但是是的。看看这两个变化:
def get_data():
while True:
yield {
"current_time": datetime.datetime.strftime(
datetime.datetime.now(), "%Y-%m-%d %H:%M:%S"
)
}
time.sleep(1)
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True
def open(self):
print("WebSocket opened")
while True:
data = next(get_data())
self.write_message(data)
Run Code Online (Sandbox Code Playgroud)
编辑02(根据OP对此答案的评论):
我看不到你的代码中的 html 文件在哪里。当我尝试时,我在浏览器中收到 404 错误
为了使用 Tornado 为您的页面提供服务,您需要一个常规(不是 websocket)处理程序来处理 HTTP 请求以获取“初始”网页。请记住,websocket处理程序仅用于处理 websocket (在 Javascript 中通过打开连接var ws = new WebSocket("ws://localhost:8888/websocket");)
然后,上述初始页面几乎会返回我在文件中手动编写的代码stack_073.html,该页面包含 Javascript,随后向 websocket 端点发起另一个/websocket请求 ( ) 例如,您可以在http://中提供 HTML /localhost:8888/script_data通过创建这个非常非常脏的处理程序:
文件stack_073.py:
import datetime
import time
import tornado.ioloop
import tornado.web
import tornado.websocket
def get_data():
while True:
yield {
"current_time": datetime.datetime.strftime(
datetime.datetime.now(), "%Y-%m-%d %H:%M:%S"
)
}
time.sleep(1)
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True
def open(self):
print("WebSocket opened")
while True:
data = next(get_data())
self.write_message(data)
class RegularSocketHandler(tornado.web.RequestHandler):
def get(self):
self.write(
"<html>"
" <header>"
" <script type=\"text/javascript\">"
" var ws = new WebSocket(\"ws://%s/websocket\");"
" ws.onmessage = function (evt) {"
" var current_time_str = JSON.parse(evt.data)['current_time'];"
" document.getElementById(\"date\").innerHTML = current_time_str;"
" };"
" </script>"
" </header>"
" <body>"
" <p id=\"date\"></p>"
" </body>"
"</html>" % (self.request.host))
def make_app():
return tornado.web.Application([
(r"/websocket", WebSocketHandler),
(r"/script_data", RegularSocketHandler)
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1252 次 |
| 最近记录: |