質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4433閲覧

PySimpleGUIでの、Tableクリック時のKeyErrorを回避する方法を教えてください。

siwasu1341

総合スコア2

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

0クリップ

投稿2021/10/19 02:15

編集2021/10/29 02:36

前提・実現したいこと

初の質問です、よろしくお願いいたします。
PySimpleGUIを使用し、毎秒スクレイピング結果を取得し、スクレイピング先に更新があった場合にデータに反映させるプログラムを作成しています。

現在はTableの行をクリックするとKeyErrorが発生してしまいますが、実現したいことはTableの行をクリックすることで、選択した行のデータを取得できるようにしたいと考えています。

発生している問題・エラーメッセージ

イメージ説明

*** tk version 8.6.9 detected.... patching ttk treeview code *** *** tk version 8.6.9 detected.... patching ttk treeview code *** Traceback (most recent call last): File "C:\Dropbox\programs\pyguisample.py", line 77, in <module> job() File "C:\Dropbox\programs\pyguisample.py", line 56, in job check_list.append(check_dic[value[0]]) KeyError: 'TABLE'

Tableの行をクリックすると、KeyErrorでプログラムが強制終了してしまいます。
eventの指定が誤っているのだと考えていますが、試したものの上手くいかなかったため、KeyErrorを回避するにはどのように指定すればよいかを教えていただきたいです。

なお、if event in '-timeout-':を削除して毎秒更新を行わないようにした場合には、Tableの行をクリックした場合にもエラーが発生しないようです。
(自動更新は実装したいと考えているので、テーブルクリックと自動更新を両立する方法を教えていただきたいです。)

該当のソースコード

Python

1import PySimpleGUI as sg 2 3sg.theme("LightGrey2") 4check_dic = { 5 '1': 'A', 6 '2': 'B' 7} 8 9#tableの内容。特に意味は無し。 10header = ['項目1',"項目2","項目3","項目4","項目5"] 11header2 = ['test','test2'] 12list1 = [ 13 ['1a', "1b", '1c', '1d', '1e'], 14 ['2a', "2b", '2c', '2d', '2e'], 15 ['3a', "3b", '3c', '3d', '3e']] 16testable = [ 17 ['1a', "1b"], 18 ['2a', "2b"], 19 ['3a', "3b"]] 20 21#左側のtableを含む、メインプログラム 22col1 = [ [sg.Text('1行目', enable_events = True)], 23 [sg.Checkbox(item[1], key = item[0])for item in check_dic.items()], 24 [sg.Button('Reset')], 25 [sg.Button('キャンセル', size=(15, 1))], 26 [sg.Table(list1, headings=header, key="TABLE", 27 background_color = '#dddddd', 28 alternating_row_color = '#ffffff', 29 display_row_numbers = True, 30 def_col_width = 25, 31 num_rows=30, 32 auto_size_columns=False, vertical_scroll_only=False)]] 33 34#サブプログラム(右側のtableです。) 35col2 = [ [sg.Table(testable, headings=header2, key="TABLE2", 36 background_color = '#dddddd', 37 alternating_row_color = '#ffffff', 38 display_row_numbers = False, 39 def_col_width = 15, 40 num_rows=40, 41 auto_size_columns=False, vertical_scroll_only=False)]] 42 43 44layout = [ 45 [sg.Column(col1), sg.Column(col2)] 46] 47 48 49window = sg.Window('サンプルプログラム', layout , resizable = True, finalize=True) 50 51#timeoutを使用し、毎秒jobが実行されるようになっています。 52def job(): 53 check_list = [] 54 for value in values.items(): 55 if value[1]: 56 check_list.append(check_dic[value[0]]) 57 58 #チェックの内容に応じて行を追加する処理。 59 if 'A' in check_list: 60 list1.insert(0, ['4a', '4b', '4c', '4d', '4e']) 61 62 if 'B' in check_list: 63 list1.insert(0, ['5a', "5b", '5c', '5d', '5e']) 64 65 window['TABLE'].update(values = list1) 66 67while True: 68 event, values = window.read(timeout = 1000, timeout_key = '-timeout-') 69 if event == sg.WIN_CLOSED or event == 'キャンセル': 70 break 71 if event == "Reset": 72 list1 = [] 73 window['TABLE'].update(values = list1) 74 75 #10秒に一度 76 if event in '-timeout-': 77 job() 78 79window.close()

試したこと

10/20
job()の内容に誤りがあるようで、

if event in '-timeout-': list1.insert(0, ['4a', '4b', '4c', '4d', '4e']) window['TABLE'].update(values = list1)

にしたところ、毎秒更新を持続させたままKeyErrorを回避し、Tableをクリックすることができました。
この状態でKeyErrorを発生させている原因を調査し、元の動作を実現できる方法を引き続き調査してみます。

(~投稿日)
・TableのKeyの変更、削除:関係なし
・eventへの「if event == "TABLE":」追加:関係なし
参考サイト:https://note.com/hotta3216/n/nb7beddc305d4

補足情報(FW/ツールのバージョンなど)

Windows10
Python3.9
他に必要な情報があればご連絡ください。

teamikl👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

エラー原因:

python

1 2check_dic = { 3 '1': 'A', 4 '2': 'B' 5} 6 7# job() 関数内 8 9 for value in values.items(): 10 if value[1]: 11 check_list.append(check_dic[value[0]]) 12

check_dic[value[0]] が KeyError を出しています。
values の内容はタイマーで実行される時は '1', '2' のみですが、
テーブルクリック時には 'TABLE', 'TABLE2' が渡ります。

check_dic 辞書には TABLE 及び TABLE2 が無い為 KeyError

大元の原因は、変数 values をjob()関数から参照している点で、
このvalues は、ユーザ操作により内容が変わります。

python

1 2while True: 3 event, values = window.read(timeout = 1000, timeout_key = '-timeout-')

目的の挙動が解らないので、解決方法は示せませんが
job() 関数内の for value in values.items() の values が意図通りかどうかを確認して見て下さい。

ループ内で書き換わる変数は、グローバル変数として運用しない方が良いです。
頻繁に書き換わる&影響範囲が広く、不具合の原因になりやすい傾向があります。

投稿2021/10/28 10:10

teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siwasu1341

2021/10/29 01:23

ありがとうございます。 メッセージを受けて、ひとまず解決することが出来ました。 ご指摘の通り、job()内でチェックボックスの内容を取得させる処理とTableクリック時にKeyを取得する処理が競合していたようです。 ここで行っていた動作としては、「チェックボックスにチェックが入っている値を取得し、自動実行させる処理を値に応じて変動させる」というものでした。 修正内容としては、今回の問題になっているcheck_listへの入力をボタン処理としてwhile_true内に移動させ、それを実行するためのボタンを一つ作成したことで解決しました。 チェックを入れてからボタンを押す必要が出たので二度手間にはなりますが、結果的にループ内処理を減らすことができ、快適になったと思います。 将来的には、チェックが付いたり外れたりしたときに自動でcheck_listの内容が変動するようにすれば、さらに効率化できそうだと考えられます。 この度はありがとうございました。助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問