Flask を使って、アップロードした dat ファイルのデータをグラフにして表示します。
UNIXコマンド:cpで上書きするか確認してくれ
$ cp file.py file1.py
でファイルをコピーして、file1.py を編集したぞー実行するぞ!という時にターミナル上で▲を押していたら、もう一回$ cp file.py file1.py
を実行してしまうこと、あるよね。ぼくだけ?
今のところ取り返しのつかないことにはなっていないけど、がっかりしちゃう。
$ cp -i file.py file1.py
とオプションをつけて実行すると、ファイルが既にある時には overwrite file1.py? (y/n [n])
と確認してくれる。
~/.bash_profile
にエイリアスを書いた。
alias cp='cp -i'
再発防止。
勉強会の宿題③ ブラウザにグラフを表示
前々回は、Flask を使って、ブラウザから dat ファイルをアップロードし、ファイルを読んでヘッダを表示できるようになった。 前回は、Pandas と Matplotlib を使って、dat ファイルからデータをグラフ化できるようになった。 今回はそれの合わせ技。
画像を埋め込む方法、 static/
ファイルの指定方法が全然分からなくて、かなり苦戦した。普通のHTMLを書く時のように path を指定したら、ダメだった。
画像を埋め込むには、 static/
という静的ファイル置き場ディレクトリを使うのが良いっぽい。
参考 👉 [Python] 軽量WebフレームワークのFlaskに入門(準備、起動、HTML、静的ファイル、GET、POSTなど) - YoheiM .NET
html ファイルのほうには
<img src="{{image}}" alt="graph">
と書き、main.py の return render_template()
の中で
image = url_for('static', filename=plot_mhdata(filename))
と渡してやると、なんかうまくいった
(このplot_mtdata(filename)
は、ファイル名を渡すとグラフの pngファイル名を返す自作関数)。
python コード
全部載せる。前々回のmain.py
に、前回の plotmhdata.py
を足して、画像埋め込みを加えた感じ。
拡張子の確認とかはしていません。自分用なので。
# main.py import os import pandas as pd from flask import Flask, request, url_for, render_template app = Flask(__name__) UPLOAD_FOLDER = './uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER import matplotlib.pyplot as plt from matplotlib import rc font = {"family": "Noto Sans CJK JP"} rc('font', **font) @app.route('/', methods = ['GET', 'POST']) def top(): if request.method == 'GET': return render_template('upload_file.html') else: if 'file' in request.files: file = request.files['file'] if file: filename = file.filename file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return render_template('dataplot.html', \ filename = filename, \ table = read_file(filename), \ image1 = plot_mhdata(filename),\ image = url_for('static', filename=plot_mhdata(filename))) # dat ファイルの最初に読み飛ばす行が何行あるか数える関数 def getHeaderRow(filename): with open(UPLOAD_FOLDER+'/'+filename) as file: for i, l in enumerate(file): if l == '[Data]\n': return i+1 return False # ヘッダの表を返す関数 def read_file(filename): headerrow = getHeaderRow(filename) if headerrow: df = pd.read_csv(UPLOAD_FOLDER+'/'+filename, skiprows = headerrow, header = 0) return df.head().to_html() # グラフを描いてpngファイル名を返す関数 def plot_mhdata(filename): xcol = 3 ycol = 4 headerrow = getHeaderRow(filename) if headerrow: df = pd.read_csv(UPLOAD_FOLDER+'/'+filename, skiprows = headerrow, header = 0) plt.figure() df.plot(title = filename.split('/')[-1], \ x = df.columns.values[xcol], \ y = df.columns.values[ycol]) plt.savefig('static/'+filename+'_'+str(xcol)+'_'+str(ycol)+'.png') plt.close('all') imgname = filename+'_'+str(xcol)+'_'+str(ycol)+'.png' else: imgname = '' return imgname if __name__ == '__main__': app.run(debug=True, threaded=True)
html ファイル
{{table|safe}}
というふうに |safe
を入れると、
python から渡した文字列にも html コードを適用してくれる。これがないと、そのまま表示されてまう(この前教えてもらった)。
<!-- dataplot.html --> <!doctype html> <html> <head> <meta charset="UTF-8"> <title> データ読み込み結果 </title> </head> <body> <h1> データを読み込みました </h1> データ:{{filename}} <br> 先頭の5行 {{table|safe}} グラフ <br> {{image1}} <img src="{{image}}" alt="graph"> </body> </html>
結果:ブラウザにヘッダ表とグラフを表示
ヘッダとグラフは モザイクとスタンプで隠してしまいました。借り物のデータなので。すいません。
「どの行をグラフ化するか選べるようにする」というのもやりたかったんですが、 次は言語処理100本ノックか統計やりたいと思います。