Edited at

Flask+websoket+Epochを使ってリアルタイムチャート

More than 1 year has passed since last update.

javascriptの勉強をかねて、webサーバから逐次データを流して、ブラウザ上でリアルタイムチャートを表示するアプリケーションをpythonの軽量WebフレームワークであるFlaskで作りました。為替とかをリアルタイムで描画するときに使えるかと思います。

サーバからのデータ送信はwebsocketを用いて行い、サーバ側でランダムに作成したデータを時刻と一緒にJSON形式で送っています。

クライアント側はjavascriptでwebsocketのデータを受けてグラフ描画を行います。

フォルダ構成

app.py

templates/index.html
static/js/d3.min.js
static/js/epoch.min.js
static/css/epoch.min.css

リアルタイムチャート作成にはd3.jsをベースにしたリアルタイムチャートライブラリであるEpochを使いました。ちなみにd3のバージョンはv3です。

websocketを使うにあたってはgevent-websocketを使っています。


app.py

import os

import json
import datetime
import random
import time
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/publish')
def publish():
if request.environ.get('wsgi.websocket'):
ws = request.environ['wsgi.websocket']
while True:
t = int(time.mktime(datetime.datetime.now().timetuple()))
ws.send(json.dumps([{"time": t, "y": random.random() * 1000},
{"time": t, "y": random.random() * 1000}]))
time.sleep(1)
return

if __name__ == '__main__':
app.debug = True
server = pywsgi.WSGIServer(('localhost', 8000), app, handler_class=WebSocketHandler)
server.serve_forever()



index.html

<html>

<head>
<title>graph test</title>
</head>
<body>
<h1>Real time chart</h1>
<div id="graph" class="epoch" style="height: 200px;"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/d3.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/epoch.min.js') }}"></script>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/epoch.min.css') }}">
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:8000/publish");
var data = [
{ label: "Series 1", values: [] },
{ label: "Series 2", values: [] },
];
var lineChart = $('#graph').epoch({
type: 'time.line',
data: data,
axes: ['left', 'right', 'bottom']
});
ws.onmessage = function(msg) {
var current = JSON.parse(msg.data);
lineChart.push(current);
};
</script>
</body>
</html>

以下を実行してlocalhost:8000にブラウザで接続してみてください。

python app.py

out.gif