1.4 ブラウザを使ったGUI

(1/1)
Pythonによるパスワード生成機
Python は、基本的に、「1.3 画面にメッセージを表示」で紹介したようにコンソール画面に処理結果を表示する。入力も、キーボードから文字入力となる。
ただ、これでは味気ないので、左図のようにGUI(グラフィカルユーザーインターフェース)を使った入出力もできることに触れておくことにする(詳しいことは、このシリーズの後半で解説する)。
(2024年7月20日)makePassword.py -- docstringをGoogleスタイルに変更.
(2024年6月15日)makePassword.py -- 標題、関数のコメントを複数行形式に変更.
(2024年6月7日)makePassword.py -- 外部ブラウザを起動できるようにした.

目次

サンプル・プログラムのダウンロード

圧縮ファイルの内容
helloWeb2.pyダイアログに1行メッセージを表示する
helloWeb2.pyダイアログに複数行のメッセージを表示する
makePassword.pyパスワード生成機

pywebviewとは

pywebview
Python でGUIを利用するにはいくつかの方法があるが、ここでは、pywebview というオープンソースのライブラリを利用することにする。無償で利用できる。
pywebview はブラウザ・モジュールを使ってGUIを実現するライブラリで、Windows、Linux、macOSで、ほぼ同じ表示ができるという特長がある。ただし、開発環境だけでなく実行環境に pywebview をインストールしておく必要がある。
以下に導入手順を解説する。

pywebviewの導入:Windowsの場合

Windows 11で pywebview を導入する手順を解説する。Windows 10でもほぼ同じ手順で導入できる。

Windowsのターミナル(コマンドプロンプト、PowerShellでもよい)を開き、"python -m pip install --upgrade pip setuptools" とコマンド入力して setuptools を導入(またはアップグレード)する。
処理が終わったら、次に、"pip install pywebview[cef]" とコマンド入力して pywebview を導入する。
コンソールは下記のような表示になり、数分すると導入が終わる。
pywebviewの導入:Windowsの場合

pywebviewの導入:Linuxの場合

aptが利用できる Linuxで pywebview を導入する手順を解説する。

Linuxのターミナルを開き、"sudo apt update" とコマンド入力して、モジュールを更新しておく。
処理が終わったら、次に、"sudo apt install -y libgtk-3-dev libwebkit2gtk-4.0-dev python3-dev python3-pip" とコマンド入力して、libgtk-3、libwebkit2gtk-4.0、python3-pip を導入する。
最後に、"pip3 install pywebview" とコマンド入力して、pywebview を導入する。

ダイアログに1行メッセージを表示する

VSCode(VisualStudio Code)を起動し、左側のファイルエクスプローラーから「新しいファイル」アイコンをクリックし、Pythonプログラム・ファイル "helloWeb1.py" を新規作成し、エディタを使って下記のプログラムを入力する。
# HTML部(ヒアドキュメントに記載) ==========================================
html = """
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
こんにちは(^^)
</body>
</html>
"""

# Pythonプログラム(API) ===================================================== try: import webview except: print("pywebviewをインストールしてください.") sys.exit()
WIDTH = 300 #ダイアログの幅(ピクセル) HEIGHT = 200 #ダイアログの高さ(ピクセル)
#pywebviewを使ってダイアログを表示する. webview.create_window("pywebview", html=html, width=WIDTH, height=HEIGHT) webview.start(http_server=False, debug=False)
ダイアログに1行メッセージを表示する
エディタ右上の (実行)アイコンをクリックすると、少し時間がかかるが、新しいダイアログを表示し、その中に "こんにちは(^^)" と表示する。
このプログラムは、大きく分けて、前半のHTML部と、後半のPythonプログラムに分かれる。
前半のHTMLの解説は省略するが、画面に "こんにちは(^^)" と表示するだけの内容である。これを文字列として、Pythonの変数 html に代入する。
イコール = の右にダブルクォーテーションが3つ連続しているが """(三連引用符)、これはヒアドキュメント文字列リテラル)などと呼ばれ、次に三連引用符が現れるまでの内容を、そのまま、改行も含めて変数に代入することができる仕組みだ。
つまり、ここでは1つのHTML文をそのまま変数 html に代入する。
後半のPythonプログラムであるが、まず、"import webview" により pywebviewを使うことを宣言する。
ここで、実行環境に pywebviewがインストールされていない場合に備え、try~catch文を使って、import文でエラーが発生したときには、ターミナルに "pywebviewをインストールしてください." と表示してプログラムを終了 "sys.exit()" する。

pywebviewを使ってダイアログを表示するのが、最後の2行だ。
まず "webview.create_window("pywebview", html=html, width=WIDTH, height=HEIGHT)" は、幅=WIDTH, 高さ=HEIGHT(単位はピクセル)の大きさのダイアログ(ウィンドウ)にブラウザ・モジュールを設定する。"hmtl=html"は、表示するHTML文として変数html を渡すことを意味する。左辺が変数だ。"pywebview" はダイアログのタイトル。
次の "webview.start(http_server=False, debug=False)" によって、実際にダイアログを表示する。表示にあたって、"http_server=False" はhttpsサーバを使わない、"debug=False" はデバッグ/ウィンドウを表示しないという働きをする。

HTML部の内容を変えてみて、表示がどう変わるか試してみてほしい。
ダイアログに1行メッセージを表示する
前半で述べたように、"helloWeb1.py" はそのままLinuxでも動く。Linux上で実行したものが左の画面である。

ダイアログに複数行のメッセージを表示する

前回作成した "hello2.py" を、ターミナルではなくダイアログに表示するプログラムが "helloWeb2.py" である。
# HTML + JavaScript部(ヒアドキュメントに記載) =============================
html = """
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script>
//メッセージを表示する.
async function dispMessage() {
	let str = await pywebview.api.helloWeb();
	document.getElementById('message').innerHTML = str;
}
</script>
</head>
<body>
<input id="click" type="button" value="クリック" onClick="dispMessage()">
<div id="message" style="color:blue;"></div>
</body>
</html>
"""

# Pythonプログラム(API) ===================================================== import atexit import sys try: import webview except: print("pywebviewをインストールしてください.") sys.exit()
WIDTH = 300 #ダイアログの幅(ピクセル) HEIGHT = 200 #ダイアログの高さ(ピクセル)
#pywebviewを使ってメッセージ・リストをダイアログに表示する. class Api: def helloWeb(self): #メッセージ・リスト(配列) messageList = ["おはよう", "こんにちは", "こんばんは"] #表示するときに改行で区切る. dispMessage = "" for message in messageList: dispMessage += message + "<br>" return dispMessage
api = Api() window = webview.create_window("pywebview", html=html, js_api=api, width=WIDTH, height=HEIGHT) webview.start(http_server=False, debug=True)
ダイアログに複数行のメッセージを表示する
エディタ右上の (実行)アイコンをクリックすると、少し時間がかかるが、新しいダイアログを表示し、その中に3行のメッセージを表示する。
前半のHTML部には表示するメッセージが見当たらない。表示するメッセージは、後半のPythonプログラムで生成し、JavaScriptを介してブラウザに表示する。
JavaScriptについては「JavaScriptによるプログラミング入門」をご覧いただくとして、結論だけ書くと、dispMessage はボタンをクリックしたときに、非同期で pywebview.api.helloWeb メソッドを呼び出し、結果を返すメソッドである。

pywebview.api.helloWeb の実体はPythonプログラムに書かれており、"def helloWeb(self): で始まる関数がそれである。
Pythonの関数は、数学の \( y = f(x) \) と同じで、引数 \( x \) を渡すと、何ブランあのデータ処理を行い、戻り値を \( y \) に代入する。def文を使ってユーザーが自由に関数を定義することができる。
関数 helloWeb の中身は、"hello2.py" の中身とほぼ同じだ。違いと言えば、HTML文では改行コード \b では改行しないので、HTMLタグ
を入れている。
生成したメッセージ dispMessage を戻り値とする。

"class Api:", "api = Api()" などは、おまじないだと考えてほしい。いずれ詳しく説明する。
webview.create_window メソッドの呼び出しで、JavaSCriptのAPI "js_api=api" を使うことを指示する。

ここまでうまく動いたら、Pythonプログラムを書き換えて、どのように動きが変わるか試してみてほしい。
ダイアログに1行メッセージを表示する
"helloWeb2.py" をLinux上で実行したものが左の画面である。

パスワード生成機

ここで少し実用的なプログラムを紹介しておこう。文字種と長さを指定してパスワードを生成するプログラム "makePassword.py" である。
パスワード生成機
ダウンロードしたZIP書庫の中に入っている "makePassword.py" を見てほしいのだが、プログラムは258行ある。そのうちの181行がHTMLとJavaScript――画面入出力のためのスクリプトだ。
パスワードを生成するPythonプログラムは、コメントや空行を除くとわずか22行――Python は短いプログラムで、そこそこ実用的なアプリを作ることができる。
今回はプログラムが動作することだけ見てもらえば十分である。いずれ詳しく説明する。

もちろんLinux上でそのまま動作する。
パスワード生成機

次回予告

次回からは Pythonの文法を1つ1つ学んでいく。まずはデータ処理の要となる変数と式からはじめる。

コラム:3層アーキテクチャ

アプリケーションを設計する際、
  1. プレゼンテーション層‥‥ユーザーが入出力を行う。
  2. アプリケーション層‥‥データの処理を行う。
  3. データ層‥‥データの検索、参照、保存を行う。
の3つにわける3層アーキテクチャという考え方がある。
3層アーキテクチャ
1960年代までの大型計算機や、1980年代半ばまでのパソコンにはGUIもデータベースもなく、FORTRAN、COBOL、BASICといったプログラミング言語が1つあれば、アプリケーションを作ることができた。
その後、macOSやWindowsのようにOS毎に特徴的なGUI機能が備わり、OracleやDb2、SQL Serverといった高機能なデータベースが登場し、各々の機能に特化したスクリプト言語やプログラミング言語が整備され、1つのプログラミング言語だけでアプリケーションを書くことが難しくなった。

今回のサンプル・プログラムで言えば、Pythonアプリケーション層を担当し、HTMLJavaScriptプレゼンテーション層を担当している。外部データ管理がないので、データ層の担当はない。
3層の担務範囲は会社やプロジェクトで決める内容になるが、一般論として、プレゼンテーション層には画面デザインと入出力データのバリデーションを担わせる。バリデーションとは、ユーザーが入力したデータが期待したものかどうか――たとえば、makePassword.py" の場合、パスワード長として入力できるのは数字だけで、アルファベットや日本語が入ったら弾くようにする。また、短すぎるパスワードは意味が無いし、かといって、むやみやたらに長いパスワードも困るので、最小値と最大値をバリデーションするようにしている。

pywebview では、アプリケーション層の処理結果がブラウザへ渡されることになるので、JavaScriptが処理しやすい JSON形式とした。JavaScript側から見ると、Pythonプログラムがクラウドサービス(WebAPI)のように見える(だから非同期処理になっている)。

データ層は、アプリケーション層のみとやり取りを行い、アプリケーション層からは切り離す。こうすることで、悪意のある第三者がデータ層に直接接触するリスクを回避できる。
そのため、冗長になるが、アプリケーション層でも必要なバリデーションを行う。

もちろん、Python だけでアプリケーションを作成することはできるのだが、今回のようにソースを変更せずに異なるOSの上で実行するのは難しくなる。また、JavaScriptには、今回も利用したが、jQuery のような便利なオープンソース・フレームワーク資産が数多くあり、これらを活用することでアプリケーションの開発スピードをアップし、一定の品質を担保することができる。

また、3層はそれぞれ別ファイルにした方が、開発や管理がしやすい。"makePassword.py" であれば、変数 html にヒアドキュメントを代入するのではなく、HTMLファイルとして分離し、webview.create_window メソッドでそのHTMLファイルを呼び出すようにする。
(この項おわり)
header