Python プログラムの実行結果を LINE Notify に通知させる.
こんにちは.あらい大先生です.
先日,第 4 回 上原研 Python 講座が開催されました.
第 3 回の時点で Python の文法を一通り学習したため,第 4 回から Python による作業の自動化を学習し始めました.
多くの人は,いったんプログラムに作業を任せたら,その様子を見守り続けることはせず,別の作業を行うと思います.
そうなると,プログラムには「作業が完了したことを教える機能」も欲しくなるでしょう.
そのため,今回のブログでは,作業が完了したら LINE で通知するプログラムを紹介します.
手順
以下の手順で Python プログラム と LINE Notify を連携させます.
- LINE Notify からメッセージを受信するプログラムを作る.
- プログラムに例外が発生した場合でも,LINE Notify からメッセージを受信できるようにする.
LINE Notify からメッセージを受信する.
最初に,LINE 公式カウントの LINE Notify [1] を友達追加します.
次に,LINE Notify のマイページ [2] へアクセスしてパーソナルアクセストークンを発行します.
本ブログでは,下記のパーソナルアクセストークンを使用します.
(注) 通常であれば,パーソナルアクセストークンを公開してはいけません.
パーソナルアクセストークンを発行したら,以下の Python プログラムを書きます.
import subprocess
def line_notify(msg='Test', token='c4Ko31jkCZKa4JNBpNYhgsQVspS1YPCToPNBu9hItlZ'):
subprocess.run(['curl', '-H', f'Authorization: Bearer {token}', '-F', f'message={msg}', 'https://notify-api.line.me/api/notify'])
line_notify()
1 行目の subprocess は標準モジュールなので,pip 等でインストールしなくても利用することができます.
subprocess.run(args) を呼び出すと args で指定されたコマンドを実行してくれる [3] ので,これを利用して Python プログラム と LINE Notify を連携させます.
3 行目で line_notify 関数を定義しています.
また,引数として msg と token を受け取れるようにしています.
msg は LINE Notify から受信したいメッセージ,token はパーソナルアクセストークンです.
今回は LINE Notify からメッセージを受信できることを確認するだけなので,どちらにもデフォルト引数を指定しています.
(注) 通常であれば,ソースコードにパスワードやパーソナルアクセストークンといった認証情報を直書きしてはいけません.
4 行目の subprocess.run() で curl コマンドを実行します.
「subprocess.run() の引数になっているリストに対して半角スペースを区切り文字として結合することで,コマンドの文字列を作成している」と考えると良いでしょう.
また,公式ドキュメントのサンプル [4] を参考に curl コマンドを書いています(-F オプションによりデータを送信することは自明なようで, "-X POST" とメソッドを指定しなくても動作するみたいです).
それでは,line_notify1.py を実行してみましょう.
上記の画像のように、LINE Notify から「[トークン名] Test」を受信することができれば成功です.
例外処理を追加する.
通常,Python プログラムの実行中に例外が発生すると,スタックトレース (Traceback) を出力してプログラムが終了します.
そのため,例外が発生しても line_notify 関数を実行してくれるように実装する必要があります.
また,せっかくなので例外が発生したことだけではなく,例外が発生した箇所や,その内容も通知してくれると良いでしょう.
そこで,先ほどの line_notify1.py を以下のように書き換えます.
import subprocess
import traceback
def line_notify(msg='Test', token='c4Ko31jkCZKa4JNBpNYhgsQVspS1YPCToPNBu9hItlZ'):
subprocess.run(['curl', '-H', f'Authorization: Bearer {token}', '-F', f'message={msg}', 'https://notify-api.line.me/api/notify'])
try:
print('in try:')
except Exception as e:
line_notify(traceback.format_exc())
else:
line_notify('has finished.')
2 行目の traceback は subprocess と同様に標準モジュールです.
例外が発生した際に,traceback.format_exc() を呼び出すと例外の情報を文字列として返してくれます [5].
7~8 行目に時間が掛かる処理を記述します.
今回は,例外が発生しない処理を適当に書いています.
9~10 行目は,例外が発生した場合の処理です.
この中で traceback.format_exc() の返り値を line_notify 関数の引数 msg に渡します.
11~12 行目は,例外が発生しなかった場合の処理です.
処理が完了したことや,実行結果が分かるようなメッセージを line_notify 関数の引数 msg に渡すと良いでしょう.
それでは,line_notify2.py を実行してみましょう.
例外は発生しなかったので,LINE Notify から 'has finished.' というメッセージを受信しました.
次に,意図的に例外を発生させるために,8 行目の print('in try:') を a += 1 に書き換えて実行してみましょう.
例外が発生した行,例外の内容を受信することができました.
改良するなら?
これだけでも十分かもしれませんが,改良が必要な場合があるかもしれません.
以下に改良案を示します.
認証情報の管理
(注) に示した通り,ソースコードにパスワードやパーソナルアクセストークンといった認証情報を直書きしてはいけません.
その代わりに,適切なアクセス制御が設定されたファイルから読み込む方法が挙げられます [6].
死活監視
上記の実装では,LINE Notify から通知が来ないときに「処理に時間が掛かっているのか,停電やフリーズによって Python そのものが動作しなくなったのか」を自分で調べる必要があります.
それでは面倒なので,「一定の回数のループ処理を実行したら,その途中結果を通知する」といった機能を加えると良いでしょう.
例外処理
line_notify2.py の 9 行目で except Exception as e: と書いているため,何らかの例外が発生すると line_notify 関数を実行してプログラムを終了してしまいます.
事前に発生を予想でき,対処も容易な例外であれば,それ専用の処理を実装してプログラムを終了させないようにするほうが良いでしょう.
おわりに
今回は Python プログラムの実行結果を LINE Notify に通知させる方法を紹介しました.
これだけではなく,予定や天気,メールなどの通知も LINE Notify に行わせることが可能です.
ぜひ「LINE Notify ○○」と検索して実装してみましょう.
参考
- LINE:LINE Notify,入手先〈https://page.line.me/?accountId=linenotify〉(参照 2022-09-09).
- LINE Notify:マイページ,入手先〈https://notify-bot.line.me/my/〉(参照 2022-09-08).
- Python:subprocess --- サブプロセス管理,Python 3.10.6 ドキュメント,入手先〈https://docs.python.org/ja/3/library/subprocess.html〉(参照 2022-09-08).
- LINE Notify:LINE Notify API Document,入手先〈https://notify-bot.line.me/doc/ja/〉(参照 2022-09-09).
- Python:traceback --- スタックトレースの表示または取得,Python 3.10.6 ドキュメント,入手先〈https://docs.python.org/ja/3/library/traceback.html〉(参照 2022-09-08).
- 情報処理推進機構 セキュリティセンター:セキュア・プログラミング講座 C/C++言語編 第7章 データ漏えい対策 コマンドラインからの情報漏えい対策,入手先〈https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c604.html〉(参照 2022-09-08).