Harukaのnote

Linuxやプログラミング,写真,旅行等の記録帳

簡単グラフ描画ライブラリPlotlyをTornado上で動かしてみる

少し前から Plotly という Python のグラフ描画ライブラリを使うようになりました.
これが Matplotlib より簡単で,シンプルなグラフ描画なら結構使えるということがわかり,自身の研究にも用いたりしています.

そして,Plotly で検索をかけると一緒に出てくるのが Dash という Web アプリケーションライブラリ.

何でも,Plotly を簡単に Web で描画するためにあるらしく,実際 Dash を使うと簡単に Web アプリケーションとして作り上げられます.

しかし,以前から私は Python の Web アプリケーションライブラリといえば Tornado を用いています.使い勝手が違う Dash で本格的に Web アプリ開発は厳しそうだなと感じたので,Plotly をうまく Tornado にのせられないか,と今回試してみました.

結果は意外とすんなりいけました.

Tornado とは

Wikipediaから

TornadoはPythonで書かれたスケーラブルでノンブロッキングなWebサーバ、Webフレームワークである。FriendFeedによって開発され、Facebookに吸収されたのちにオープンソース化された。

ja.wikipedia.org

環境

OS: Open SUSE tumbleweed
Python version: Python 3.6.8

ライブラリのインストール

$ 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 にします.

これであとは実行するだけです.

実行

$ python app.py

そして,
http://localhost:8888/
にアクセスすると,以下のような画面が表示されており,完成です.

f:id:krulcifer-einfolk-fafnir:20190114230238p:plain
実行結果

最後に

正直この記事はニッチな要望というか,自分のメモのためにだけ書いているようなものです.
わざわざ Dash を使わずに Tornado で Plotly を使う人はいないと思います.
しかし,私は以前プロコン用に Tornado でそこそこ機能をつけた Web アプリを開発した経験があり,Tornado の書きやすさ,特に素の Python に近い書き方で実装できる点が忘れられずやってみました.
こんな使い方は推奨しませんが,Tornado は本当にいいと思うので, bottle や Flask, django 以外の選択肢として選んでみても面白いと思います.

GitHub で同じコードを公開しています.
github.com