Python + PySimpleGUI でMySQLテーブル表示

今のレベルで記事を書いていても誰の参考にもならないだろう。いつもの通り自分のためのメモである。
前回の続き。

目次

サンプルデータベース

最初にやることは MySQL データベースとの接続。
ネット検索しても、適当にコード内でデータを書いて済ませるものばかりで実感出来ず、かなり苦労した。
中には、後で分かった「コード書いてるだけで絶対実行してないやろ!?」という雑なものもあり、運悪くそのページを最初に参考にしてしまったために必要以上の苦難となった。
「あとは自分で勉強努力しろや」なのかもしれないが、初学者としては実例がないとトライしようがないのだ。
とにかく手を動かさないと座学だけでは一歩も進めない。

さいわい、別な目的で 1年前に作成してあったデータベースが手元にあるのでこれを利用する。
※データ元は某サイトで自動生成してくれた架空の名簿(サイト名は忘れた)

サンプルコードの解説(自分用)

PythonでMySQLデータベースを”簡便に”扱うには mysql.connector ライブラリが必要。
WindowsのODBCは利用出来ない(と思う)ので、Pythonのライブラリをインストールする。
コマンドプロンプトで pip install mysql.connector と入力して少し待つと処理が完了する。
インストーラーのバージョンアップ通知が最後に出るが、一旦無視して先に進む。

MySQLに接続するための下準備

冒頭で PySimpleGUI とともに mysql.connector をインポートしておく。
今回はクラシカルな雰囲気のテーマを使用するが、何でも良い。
これまではとにかく動かすことだけを考えて進めて来たのでエラー処理は何もして来なかったが、ここ(接続時)はさすがに避けて通れない。

try : 例外発生時処理

try: で始まり、エラー発生時は except: までジャンプする。その場合は後の処理を書いて終わる。

import PySimpleGUI as SG
import mysql.connector  # コネクト用ライブラリ

SG.theme("Default1")    #伝統的なWindows 風テーマ
try:    #接続失敗対策
    CN=mysql.connector.connect(
    user="paradox",host="192.168.1.20",password="パスワード",database="sample")
    print("-- MySQL接続OK ( ゚∀゚)v --")
except:
    SG.popup("接続失敗!!")
    SG.Window.close

ODBC方式でもさんざん書いて慣れているので、ここはスムーズに書けた。mysql.connector.connect (関数?)でデータベースへの接続文字列を生成して変数に代入。別に実害はないが一応パスワードは仮の文字列に変えてある。
正常に接続できたら、エディタのターミナルウィンドウに — MySQL接続OK ( ゚∀゚)v — と表示される。

cursor.execute : SQL文発行とカーソル取得

SQL文はMySQLの仕様に沿って書く。一行コマンドでは末尾のセミコロンは省略可である。

# MySQL のデータ取得
SQL =("SELECT ID,氏名,電話番号,メールアドレス FROM 人名簿マスタ limit 50")

cursor=CN.cursor()
cursor.execute(SQL)

SQLを実行する execute はもはや説明不要。問題は、cursor(カーソル)である。高度なデータベース処理では理解必須のようでかなり概念が難解そうだがとりあえずは「サーバー側での行位置(ポインター)」と覚えておく。

fetch : テーブルのデータ取得

DATA=cursor.fetchall()  # 全レコードを取得
CN.close

カーソル名.fetchall() でSQL文実行で受け取った全データを適当な変数名 DATA に代入する。
その後は用がないので接続状態を閉じておく。fetchone とか fetchmany などもあるが今は利用機会はない。
たったこれだけ。いやもう呆気ないくらいにカンタンだった( ゚∀゚)。
DATA変数に入れたまでは良いが、しかしその後がホント大変・・・これ、どうやってテーブル表示する?? (;`ー´)

テーブルの任意の行と列を取り出すには??

とりあえず print(DATA) としてみると・・・SQL で limit 50 指定してるので50名分ある。

-- MySQL接続OK ( ゚∀゚)v --
[(1, '菅原 義美', '06-7257-1096', 'sugawara12@example.org'), (2, '綿貫 冬樹', '0537-71-4138', 
'watanuki_fuyuki@example.jp'), (3, '浅野 洋樹', '082-644-4580', 'hiroki_asano@example.org'), (4, '仙石 みゆき', '03-1348-9754', 'sengoku_1221@example.com'), (5, '水島 亮一', '06-7597-9778', 'mizushimaryoichi@example.co.jp'), (6, '小峰 信宏', '06-6556-8643', 'komine324@example.com'), (7, '高瀬 貴一', '06-6668-5123', 'takasekiichi@example.com'), (8, '大西 宜子', '0124-69-7466', 'onishi_noriko@example.jp'), (9, '園田 光', '03-5093-7010', 'sonoda_511@example.com'), (10, '白澤 剛', '044-551-7613', 'shirasawa_620@example.com'), (11, '井上 健太', '0952-50-4380', 'inoue129@example.com'), (12, '福嶋 朋', '0796-31-0646', 'tomofukushima@example.co.jp'), (13, ' 
亀田 明子', '048-932-9786', 'kameda_akiko@example.net'), (14, '綿貫 まゆみ', '0254-08-7045', 'mayumiwatanuki@example.jp'), (15, '山田 浩介', '01267-3-7544', 'kosukeyamada@example.co.jp'), 
(16, '池内 俊介', '0791-99-3414', 'shunsukeikeuchi@example.net'), (17, '小俣 宏昭', '0980-92-7270', 'hiroaki_omata@example.com'), (18, '金城 薫', '045-031-0600', 'kinjo_930@example.net'), 
                        :
                        :   
 (46, '阿部 雅浩', '0584-69-7100', 'abe121@example.net'), (47, '小山 謙一', '03-4509-6984', 'koyamakenichi@example.com'), (48, '田中 彩加', '06-2045-8496', 'ayaka_tanaka@example.ne.jp'), (49, '飯塚 孝志', '03-8676-0024', 'iizuka_118@example.com'), (50, '内田 こずえ', '03-1215-1645', 'kozueuchida@example.ne.jp')]

テーブル構造のまま出力されたことは理解できる。
1行ずつ ( ) でCSVスタイルで括られていることもすぐ分かる。
それなら、順次処理のコードを書けばいともカンタン??
それにしても、これどうやるんやろ? 中級者なら「何で分からんのや??」なのだろうが、 PySimpleGUI 内での例がまったく見つけられなかった。Pythonの言語仕様の基本をちゃんと学ばなかったツケが来たな・・・( ;´・ω・`)
とりあえず近所の書店に走ったが、田舎の書店ではPythonの参考書なんて数冊しかない。
手に取った3冊目でようやくMySQL接続の説明を見つけたが、わずか3ページほどで概念的内容だけ。
しかし、ヒントはあった !! やはり筋道どおり学ぶには書籍に限るなと見直した。買わんかったけど(;`ー´)

“+CLICKED+”イベントで行列処理実現

各行はリスト型として処理できる。がしかし、それらが大枠として [ ]で括られている。表(テーブル)なので当たり前とはいえDATA の中身は二次元配列になっているのだ。

SG.Table(key="-リスト-",headings= 見出,col_widths=列幅,values=list(DATA),justification="left",
              num_rows=20,auto_size_columns=False,enable_click_events=True)]

PySimpleGUI の Table ウィジェットにリスト型として DATA を代入してみるとあっさりと表示してくれた。

さて。その中の任意の行の列値を取り出すにはどうするか。
カンタンそうに思えるが、どう書いたら良いのか分からなかった。公式サイトでも

テーブルウィジェットの enable_click_events イベント駆動説明で、
テーブルがクリックされたときに (行、列) クリック データを提供する

としか書かれていないよ。はぁ~・・・( ;´・ω・`)
よし、少し真面目に勉強してみるか。

tuple : タプルの基本

DATA変数の中身は ( ) 内でカンマ区切り文字列が行となっている。
これは少し前にコンボボックス編でおぼえた”タプル型”のようだ。
一次元の値リストをもつタプルの構造は 変数=(値,値,値) で作成できる。
作成された変数の型は type() 関数で確認でき、リスト内の値は角括弧の 変数名[インデックス] で取得する。

# リストから位置を指定して値を取り出す
N=3

文字列=(2,8,1,95,200)
print("数値列:",文字列,文字列[N],type(文字列))
文字列=(2,365,0,"大阪市中央区",1,95,200)
print("混在列:",文字列,文字列[N],type(文字列))
文字列="奈良","大阪","和歌山","群馬"
print("文字列:",文字列,文字列[N],type(文字列))

配列はゼロから始まるので 文字列[N] は4番目の値になる。

数値列: (2, 8, 1, 95, 200) 95 <class 'tuple'>
混在列: (2, 365, 0, '大阪市中央区', 1, 95, 200) 大阪市中央区 <class 'tuple'>
文字列: ('奈良', '大阪', '和歌山', '群馬') 群馬 <class 'tuple'>

実行結果は・・・すべて <class ‘tuple’> 合ってる 。タプル型ではなくタプルクラスと呼ぶのが正しいのだろう。
“class”の概念自体は特別に難しいとは感じないが、用法は広範囲で難解な場面が多いのでスルーしたい。
VBコードが染み付いたアタマでは”型”と呼ぶ方が覚えやすいので、今はそうしておく。( ´ー`)
文字列は教科書通りのシングル引用符で返されるが、気にしないことにする。
すると、DATAを式で表すと [(タプル),(タプル),(タプル),(タプル)・・・,(タプル)] となる。

list : リスト型

丸かっこ( ) の代わりに文字列全体を角括弧[ ] でくるとリスト型の文字列となる。

文字列=["奈良","大阪","和歌山","群馬"]
print("リスト:",文字列,文字列[N],type(文字列))

実行結果は、タプル型ではなくリスト型になった。

リスト: ['奈良', '大阪', '和歌山', '群馬'] 群馬 <class 'list'>

タプル型を [ ] で入れ子にしてやるとリスト型になるようだ。これを理解するまで半日以上費やした。
わざわざこんなことをやってるのは PySimpleGUI のテーブルウィジェットでは仕様として表データの格納に使われる values オプションがリスト型に指定されているため。

テーブル データは 2 次元テーブルとして表されます。行のリストであり、各行はテーブル内の行を表します。(作成者の公式説明より)

本来はこれらのような基本知識を先に学んでおくべきではあるが、それはやらない。
よほど挫折しない限り、失敗してその都度覚える方針は変わらない。
自分の目標達成にはPython言語の1%も必要ないと考えているためだ。吉と出るか凶と出るか。(;`ー´)

サンプルコードでは各種オプション引数を使っているが、values=list(DATA) だけでも機能する。
オプション機能の多くは外観に関するもの。他にも多くの機能があるが、次号で解説。

[SG.Table(key="-リスト-",values=list(DATA),headings= 見出,col_widths=列幅,justification="left",
              num_rows=20,auto_size_columns=False,enable_click_events=True)],

リストの入れ子構造で行と列の値を取得!!

これでだいぶ目標に近づいた。DATA変数の内容を文字列にして [ ] で括って変数に代入してみる。

データ値=[
(1, '菅原 義美', '06-7257-1096', 'sugawara12@example.org'), (2, '綿貫 冬樹', '0537-71-4138', 
'watanuki_fuyuki@example.jp')]

print("DATAの先頭行は:",データ値[0])

実行結果。無事に先頭行が表示された。

DATAの先頭行は: (1, '菅原 義美', '06-7257-1096', 'sugawara12@example.org')

さて、ここから”氏名”を取り出すにはどうするか。ここでも試行錯誤したが結果は単純で引数の連結。

print("DATAの先頭行の氏名は:",データ値[0][1]) ➡ DATAの先頭行は: 菅原 義美

ここまで来たなら目標達成が近いように見えるが、テーブルのクリックでこれをどう実装するか・・・
結局これが一番の難題となった( ;´・ω・`)
以下、次号に続く

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次