Flaskを使ってみる

pythonスクリプトのWEB対応 その4


前回のプログラムで、表示ロジックは完成しま したので、
これをブラウザーで表示できるように変更します。

以下の手順でFlaskをインストールします。

ubuntu18.04ではpython3.6がインストールされていますが、このバージョンは2021年12月にサポートが切れてます。
システムインストール時(デフォルト)のpython3をバージョンアップすると、aptがエラーになる事が有ります。
pyenv経由でpythonをインストールすると、システムインストール時(デフォルト)のpython3を変更することなく、
好きなバージョンのpythonをインストールすることができます。
pyenvについては色々なところで紹介されていますが、まっさらな環境にインストールするためには、
いくつかのパッケージを事前にインストールしておく必要が有ります。
こちらにまとめておきました。

aptでインストールできるpipはバージョンが古いので、一度古いバージョンを入れてからアップデートします。
pipでパッケージをインストールする時は、wheel形式のファイルをダウンロードします。
wheelモジュールが古いと、インストール時にワーニングやエラーになる事が有るので、こちらも更新しておきます。
pipとwheelの関係はこちらに 簡素にまとまっています。
$ python3 --version
Python 3.7.3

$ sudo apt install python3-pip python3-setuptools

$ python3 -m pip -V
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

$ python3 -m pip install -U pip

$ python3 -m pip -V
pip 20.3.1 from /home/orangepi/.local/lib/python3.7/site-packages/pip (python 3.7)

$ python3 -m pip install -U wheel

$ python3 -m pip install -U Werkzeug

$ python3 -m pip install -U flask

次に前回のプログラムをFlaskで使えるように少し変更します。
前回の表示関数 display() はそのまま利用して、Flaskで必要な所だけ追加します。

<monitor4.py>
#!/usr/bin/env python
#-*- encoding: utf-8 -*-

import commands
import os.path
import datetime
import locale
import time
import signal
from flask import Flask, render_template, request
app = Flask(__name__)


ITEMC = 0
ITEMS = {
  0 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  1 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  2 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  3 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  4 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  5 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  6 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  7 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  8 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''},
  9 : {'time' : '', 'cpu' : '', 'item1' : '' , 'item2' : '',  'item3' : '', 'item4' : '', 'item5' : '', 'item6' : '', 'item7' : '', 'temp1' : '', 'temp2' : ''}
   }

def addItem(time,cpu,item1,item2,item3,item4,item5,item6,item7,temp1,temp2):
  global ITEMC
#  print "ITEMC:" + str(ITEMC)
  if ITEMC == len(ITEMS):
    shiftItem()
    ITEMC = ITEMC-1
  ITEMS[ITEMC]['time'] = time
  ITEMS[ITEMC]['cpu'] = cpu
  ITEMS[ITEMC]['item1'] = item1
  ITEMS[ITEMC]['item2'] = item2
  ITEMS[ITEMC]['item3'] = item3
  ITEMS[ITEMC]['item4'] = item4
  ITEMS[ITEMC]['item5'] = item5
  ITEMS[ITEMC]['item6'] = item6
  ITEMS[ITEMC]['item7'] = item7
  ITEMS[ITEMC]['temp1'] = temp1
  ITEMS[ITEMC]['temp2'] = temp2
  ITEMC = ITEMC + 1

  for i in ITEMS:
#    print "i=" + str(i),
    print ITEMS[i]['time'],
    print ITEMS[i]['cpu'],
    print ITEMS[i]['item1'],
    print ITEMS[i]['item2'],
    print ITEMS[i]['item3'],
    print ITEMS[i]['item4'],
    print ITEMS[i]['item5'],
    print ITEMS[i]['item6'],
    print ITEMS[i]['item7'],
    print ITEMS[i]['temp1'],
    print ITEMS[i]['temp2'],
    print


def shiftItem():
  for i in range(len(ITEMS)-1):
    ITEMS[i]['time'] = ITEMS[i+1]['time']
    ITEMS[i]['cpu'] = ITEMS[i+1]['cpu']
    ITEMS[i]['item1'] = ITEMS[i+1]['item1']
    ITEMS[i]['item2'] = ITEMS[i+1]['item2']
    ITEMS[i]['item3'] = ITEMS[i+1]['item3']
    ITEMS[i]['item4'] = ITEMS[i+1]['item4']
    ITEMS[i]['item5'] = ITEMS[i+1]['item5']
    ITEMS[i]['item6'] = ITEMS[i+1]['item6']
    ITEMS[i]['item7'] = ITEMS[i+1]['item7']
    ITEMS[i]['temp1'] = ITEMS[i+1]['temp1']
    ITEMS[i]['temp2'] = ITEMS[i+1]['temp2']

def ProcessStats():
  global LoadAvg
  global CpuFreq
  global SocTemp
  global PMICTemp
  global CPULoad
  global SystemLoad
  global UserLoad
  global NiceLoad
  global IOWaitLoad
  global IrqCombinedLoad

  LoadAvg = commands.getoutput("cut -f1 -d ' ' </proc/loadavg")
  CpuFreq = commands.getoutput("awk '{printf (\"%0.0f\",$1/1000); }' </sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq")

  Sensors="/etc/armbianmonitor/datasources/"
  SocTemp = 0
  path=Sensors + "soctemp"
  if os.path.isfile(path):
    SocTemp = commands.getoutput("cat " + path)
  PMICTemp = 0
  path=Sensors + "pmictemp"
  if os.path.isfile(path):
    PMICTemp = commands.getoutput("awk '{printf (\"%0.1f\",$1/1000); }' <" + path)

  CpuStat= commands.getoutput ("awk -F\" \" '{print$1\"\t\"$2\"\t\"$3\"\t\"$4\"\t\"$5\"\t\"$6}' </tmp/cpustat")
  list = CpuStat.split()
  CPULoad=list[0]
  SystemLoad=list[1]
  UserLoad=list[2]
  NiceLoad=list[3]
  IOWaitLoad=list[4]
  IrqCombinedLoad=list[5]   

def display():
  ProcessStats()
  d = datetime.datetime.today()
  time = '{0:02d}:{1:02d}:{2:02d}:'.format(d.hour, d.minute, d.second)
#  print time,
  cpu = '{0:>4s}MHz'.format(CpuFreq)
#  print cpu,
  item1 = '{0:>5s}'.format(LoadAvg)
#  print item1,
  item2 =  '{0:>3s}%'.format(CPULoad)
#  print item2,
  item3 =  '{0:>3s}%'.format(SystemLoad)
#  print item3,
  item4 =  '{0:>3s}%'.format(UserLoad)
#  print item4,
  item5 =  '{0:>3s}%'.format(NiceLoad)
#  print item5,
  item6 =  '{0:>3s}%'.format(IOWaitLoad)
#  print item6,
  item7 =  '{0:>3s}%'.format(IrqCombinedLoad)
#  print item7,
  temp1=''
  if SocTemp > 0:
    temp1 = '{0:>4s}'.format(SocTemp)
#    print temp1,
  temp2=''
  if PMICTemp > 0:
    temp2 = '{0:>4s}'.format(MPICTTemp)
#    print temp2,
#  print
 
  addItem(time,cpu,item1,item2,item3,item4,item5,item6,item7,temp1,temp2)

@app.route("/")
def main():
   display()

   templateData = {
      'items' : ITEMS
   }

   return render_template('monitor4.html', **templateData)


if __name__ == "__main__":
   app.run(host='0.0.0.0', port=80, debug=True)

テンプレートファイル(monitor4.html)を準備します。
<monitor4.html>
<!DOCTYPE html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta http-equiv="refresh" content="5;url="/">
   <title>Current Status</title>
</head>

<body>
   <h1>CPU Frequency and Status</h1>

   <table border="1" cellpadding="2" cellspacing="2">
   <tbody>
   <tr style="color:#ffffff;" bgcolor="#800000">
   <th valign="top">Time</th>
   <th valign="top">CPU</th>
   <th valign="top">load</th>
   <th valign="top">%cpu</th>
   <th valign="top">%sys</th>
   <th valign="top">%usr</th>
   <th valign="top">%nice</th>
   <th valign="top">%io</th>
   <th valign="top">%irq</th>
   <th valign="top">CPU</th>
   <th valign="top">PMIC</th>
   </tr>


{% for i in items %}
   <tr>
   <td>{{ items[i].time }}</td>
   <td>{{ items[i].cpu }}</td>
   <td>{{ items[i].item1 }}</td>
   <td>{{ items[i].item2 }}</td>
   <td>{{ items[i].item3 }}</td>
   <td>{{ items[i].item4 }}</td>
   <td>{{ items[i].item5 }}</td>
   <td>{{ items[i].item6 }}</td>
   <td>{{ items[i].item7 }}</td>
{% if items[i].temp1 == "" %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp1 }}℃</td>
{% endif %}


{% if items[i].temp2 == "" %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp2 }}℃</td>
{% endif %}

{% endfor %}
   </tbody>
   </table>

</body>
</html>

<ディレクトリ構成>
Python Code $HOME/flask/monitor4.py
テンプレート $HOME/flask/templates/monitor4.html

WEBサーバーを起動します。
$ cd $HOME/flask
$ sudo python ./monitor4.py

WEBサーバーを起動すると以下の画面が表示されます。


WindowsPCなどでブラウザを起動し、アドレスバーに「http://OPIのIPアドレス」を指定します。


Flaskを使えばpythonで表示できるものはすべてブラウザーで表示することができるようになります。

続く
...