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

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

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

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Python

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

Q&A

解決済

1回答

3327閲覧

tkinterのプログラムをマルチスレッド化できない

awgfawg

総合スコア4

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Python

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

0グッド

0クリップ

投稿2022/03/01 06:16

Tkinterで作ったGUI表示プログラムのマルチスレッド化を目指していますが、例外が発生して実行できません。

import sys import tkinter import concurrent.futures import logging def ShowWindow(): root = tkinter.Tk() root.mainloop() #/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_ #main #/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_ with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: f1 = executor.submit(ShowWindow)
2022-03-01 15:04:18.616 Python[3926:78677] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!' *** First throw call stack: ( 0 CoreFoundation 0x00007ff802a4ef0b __exceptionPreprocess + 242 1 libobjc.A.dylib 0x00007ff8027afb9d objc_exception_throw + 48 2 CoreFoundation 0x00007ff802a778ca -[NSException raise] + 9 3 AppKit 0x00007ff805429171 -[NSWindow(NSWindow_Theme) _postWindowNeedsToResetDragMarginsUnlessPostingDisabled] + 321 4 AppKit 0x00007ff805414ee6 -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1287 5 AppKit 0x00007ff8054149d9 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 42 6 libtk8.6.dylib 0x000000010c8207fd TkMacOSXMakeRealWindowExist + 705 7 libtk8.6.dylib 0x000000010c82040e TkWmMapWindow + 63 8 libtk8.6.dylib 0x000000010c78650b Tk_MapWindow + 158 9 libtk8.6.dylib 0x000000010c78eed3 MapFrame + 59 10 libtcl8.6.dylib 0x000000010c56d38a TclServiceIdle + 75 11 libtcl8.6.dylib 0x000000010c551c5b Tcl_DoOneEvent + 337 12 libtk8.6.dylib 0x000000010c813263 TkpInit + 762 13 libtk8.6.dylib 0x000000010c78774d Initialize + 2402 14 _tkinter.cpython-37m-darwin.so 0x000000010c329dc4 Tcl_AppInit + 84 15 _tkinter.cpython-37m-darwin.so 0x000000010c324dee Tkapp_New + 606 16 _tkinter.cpython-37m-darwin.so 0x000000010c324945 _tkinter_create + 373 17 python3.7 0x000000010bbed1c6 _PyMethodDef_RawFastCallKeywords + 646 18 python3.7 0x000000010bbec599 _PyCFunction_FastCallKeywords + 41 19 python3.7 0x000000010bcbc456 call_function + 470 20 python3.7 0x000000010bcb90e1 _PyEval_EvalFrameDefault + 27745 21 python3.7 0x000000010bcbd16f _PyEval_EvalCodeWithName + 2639 22 python3.7 0x000000010bbec047 _PyFunction_FastCallDict + 455 23 python3.7 0x000000010bbed503 _PyObject_Call_Prepend + 131 24 python3.7 0x000000010bc3ec2f slot_tp_init + 175 25 python3.7 0x000000010bc3a504 type_call + 292 26 python3.7 0x000000010bbec3af _PyObject_FastCallKeywords + 575 27 python3.7 0x000000010bcbc4c2 call_function + 578 28 python3.7 0x000000010bcb90e1 _PyEval_EvalFrameDefault + 27745 29 python3.7 0x000000010bbeca7d function_code_fastcall + 237 30 python3.7 0x000000010bcb93f0 _PyEval_EvalFrameDefault + 28528 31 python3.7 0x000000010bbeca7d function_code_fastcall + 237 32 python3.7 0x000000010bcbc4e3 call_function + 611 33 python3.7 0x000000010bcb90c7 _PyEval_EvalFrameDefault + 27719 34 python3.7 0x000000010bbeca7d function_code_fastcall + 237 35 python3.7 0x000000010bcb93f0 _PyEval_EvalFrameDefault + 28528 36 python3.7 0x000000010bbeca7d function_code_fastcall + 237 37 python3.7 0x000000010bcbc4e3 call_function + 611 38 python3.7 0x000000010bcb90c7 _PyEval_EvalFrameDefault + 27719 39 python3.7 0x000000010bbeca7d function_code_fastcall + 237 40 python3.7 0x000000010bcbc4e3 call_function + 611 41 python3.7 0x000000010bcb90c7 _PyEval_EvalFrameDefault + 27719 42 python3.7 0x000000010bbeca7d function_code_fastcall + 237 43 python3.7 0x000000010bbed503 _PyObject_Call_Prepend + 131 44 python3.7 0x000000010bbec6b8 PyObject_Call + 136 45 python3.7 0x000000010bd46af7 t_bootstrap + 71 46 libsystem_pthread.dylib 0x00007ff80290c4f4 _pthread_start + 125 47 libsystem_pthread.dylib 0x00007ff80290800f thread_start + 15 ) libc++abi: terminating with uncaught exception of type NSException [ファイルパス]: line 4: 3926 Abort trap: 6 Python [ファイルパス]

tkinterのプログラムはメイン以外で実行してはいけない仕様なのでしょうか??
原因と解決方法を教えてほしいです。よろしくお願いします

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

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

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

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

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

ppaul

2022/03/01 07:25

なぜ、マルチスレッドにしたいのですか?
awgfawg

2022/03/01 07:50

かなり要約して説明します。 ログを常に監視し 、内容に応じてGUIに表示するプログラムを考えています。 技術的な問題で「GUIを表示するプログラム」と「ログ監視するプログラム」を別々に実行する必要があるからです。
guest

回答1

0

ベストアンサー

問題自体は、プラットフォーム側の制限です。

※ 実行時設定ではなく、Python/tk をビルドするときの環境設定です。

tkinter 自身は、そのような制限はありませんが、
一般的に GUIプログラムのメインループは main thread で動かしたほうが良いです。

  • 複数のイベントループを動かす → マルチスレッド、単一スレッドで複数のイベントループの結合

 ※ 例) schedule や asyncio 等のイベントループが競合するライブラリと tkinter を同時に使いたい、等。

  • 複数の tkinter アプリを動かす → マルチプロセスを検討、別プロセスのmain threadで動かします
  • 複数のウィンドウを使う → tkinter.Toplevel
  • アニメーション等のGUIの絡むバックグラウンド処理 → GUIの提供するタイマー(tkinterでは after関数)を利用

投稿2022/03/01 07:32

編集2022/03/01 08:52
teamikl

総合スコア8817

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

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

awgfawg

2022/03/01 08:02 編集

この環境でGUIアプリを作成する場合、GUIの処理はすべてmainスレッドで完結しなければならないという理解でよろしいですか?
teamikl

2022/03/01 08:27 編集

> GUIの処理はすべてmainスレッドで完結しなければならない そうですね。他の環境だったとしても GUI の処理は main スレッドで行う構成を 割と強めに推奨します。(理由: 動かすことは可能でも、他の注意点・問題が多くなる為) GUIプログラミング等の「イベント駆動型」と呼ばれる構造のプログラムは、 イベントループ (tkinter では mainloop) を持つのですが、 イベントループを動かしているスレッド内で処理しないと、 スレッドセーフなプログラムにはなりません。別スレッドからスレッドをまたぐアクセスは基本NG イベントループ自体を別スレッドにすれば・・・と思われるかもしれませんが、 tkinter の場合、(他のGUIライブラリと比べて)少しだけ状況が特殊で ライブラリが稼働してるスレッドとの間でtcl/tk のコマンドを通信して行います。 スレッドセーフでないプログラムは、一見エラーも出ずに正しく動いているように見えて 稀なタイミングで問題が起こることが有り、問題の再現が難しく デバッグがとても難しくなる傾向があります。 GUIライブラリによっては、ライブラリ側でGUI操作のメソッド呼び出しを main スレッドかどうかをチェックしているものもあります。 特殊な理由がない限りは GUI のイベントループは main スレッドで動かすのをおすすめします。
awgfawg

2022/03/01 08:51

返信ありがとうございます。 別のスレッドの処理をトリガーにしてメインスレッドで動いているtkinterにイベントを起こさせる手段はないのでしょうか? 例: 別スレッドでログファイルの変化を感知したら、メインスレッドで動いているGUIプログラムに変化を起こさせる。
teamikl

2022/03/01 09:15 編集

> 別のスレッドの処理をトリガーにしてメインスレッドで動いているtkinterにイベントを起こさせる手段はないのでしょうか? (A) event_generate が tkinter で唯一のスレッドセーフな通知手段です。  但し制限があり、引数は渡せません。 (B) 次点で after_idle に関数・引数を指定することで、  イベントループ側のスレッドで関数を呼び出させることが可能です。 (C) 独自に Queue を使って、別スレッドで queue.put メイン側で  タイマーを使って、定期的に queue.get_nowait で読み出し。  読みだしたデータに応じた処理をする。 (D) C の方法をライブラリで実装した mttkinter というライブラリがあります。  但し、Python2.x 用(保守は8年前で停止) 簡単なのは(A)(B)ですが、スレッドの生存期間とtkinterの生存期間に注意が必要です。 きちんと管理できてないと、プログラム終了時にエラーが出たり出なかったりすることがあります。 (C)はライブラリに依存しない方法、単体テストや別GUIに移植が視野も場合はCをオススメします。
awgfawg

2022/03/01 16:45

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問