少し前から Plotly という Python のグラフ描画ライブラリを使うようになりました.
これが Matplotlib より簡単で,シンプルなグラフ描画なら結構使えるということがわかり,自身の研究にも用いたりしています.
そして,Plotly で検索をかけると一緒に出てくるのが Dash という Web アプリケーションライブラリ.
何でも,Plotly を簡単に Web で描画するためにあるらしく,実際 Dash を使うと簡単に Web アプリケーションとして作り上げられます.
しかし,以前から私は Python の Web アプリケーションライブラリといえば Tornado を用いています.使い勝手が違う Dash で本格的に Web アプリ開発は厳しそうだなと感じたので,Plotly をうまく Tornado にのせられないか,と今回試してみました.
結果は意外とすんなりいけました.
Tornado とは
TornadoはPythonで書かれたスケーラブルでノンブロッキングなWebサーバ、Webフレームワークである。FriendFeedによって開発され、Facebookに吸収されたのちにオープンソース化された。
ライブラリのインストール
$ pip install plotly tornado
Tornadoのコード
app.py
import tornado.ioloop import tornado.web import os import plot # '/' が呼ばれたときの処理 class MainHandler(tornado.web.RequestHandler): def get(self): # "index.html" と一緒にグラフのデータを渡す self.render("index.html", graph_01=plot.graph_01() # 描画したいグラフの呼び出し ) # application オブジェクトの作成 def make_app(): return tornado.web.Application( [ (r"/", MainHandler), # '/' と MainHandlerの結びつけ ], template_path=os.path.join(os.getcwd(), "templates"), static_path=os.path.join(os.getcwd(), "static"), ) if __name__ == "__main__": app = make_app() app.listen(8888) # ポート番号の選択 tornado.ioloop.IOLoop.current().start() # 実行
次に templates というディレクトリを作成し,その下に index.html を置きます.
index.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Display Demo</title> </head> <body> <h1> Display Demo </h1> <div id="main"> {% autoescape None %} <p>{{graph_01}}</p> </div> </body> </html>
index.html 内の
{{graph_01}}
の部分でグラフを描画しています.{{ }} は Tornado が html 内で変数展開するための表記です.
また,
{% autoescape None %}
も必要であり,これは render で受け取った文字列を素の文字列として表示するのではなく,動作するコードとして描画するための表記です.
これに関しては以前にこのブログで書いています.
haruka0000.hatenablog.com
それでは次に Plotly 部分を説明します.
Plotlyのコード
plot.py
import plotly import plotly.graph_objs as go def graph_01(): plot_obj = plotly.offline.plot({ "data": [go.Scatter(x=[1, 2, 3, 4], y=[4, 5, 2, 8])], # 描画したいデータ "layout": go.Layout(title="hello world"), # タイトル }, auto_open=False, output_type="div") # 出力タイプを'file'から'div'へ変更 return plot_obj
これだけです.
Plotly をオフラインで使い,描画部分のみを利用しています.
今回のであれば,オンライン部分を Tornado が受け持っていることになります.
output_type を file にすると,結果が html で保存されますが,今回は html のデータそのものが欲しいので,div にします.
これであとは実行するだけです.
最後に
正直この記事はニッチな要望というか,自分のメモのためにだけ書いているようなものです.
わざわざ Dash を使わずに Tornado で Plotly を使う人はいないと思います.
しかし,私は以前プロコン用に Tornado でそこそこ機能をつけた Web アプリを開発した経験があり,Tornado の書きやすさ,特に素の Python に近い書き方で実装できる点が忘れられずやってみました.
こんな使い方は推奨しませんが,Tornado は本当にいいと思うので, bottle や Flask, django 以外の選択肢として選んでみても面白いと思います.
GitHub で同じコードを公開しています.
github.com