wxPythonでsleepすると応答なしになる件
プログラミング言語Python(パイソン)に関する話です。
目次
wxPythonでsleepを使うと応答なし
先日、wxPythonでsleep()を使うというイレギュラーなプログラムを作ったときに、プログラムが応答なし(フリーズする)になるという現象に遭遇しました。
この問題と解決方法について記載します。
確認環境
- Windows 10 Home(64bit)
- Python 3.8.2(64bit)
- wxPython 4.0.7.post2
一応Python 3.8の32bit版と、Python 3.7の64bit版も試しましたが同じ状況でした。
現象について
当方の環境では、
- メイン処理の中のtime.sleep()を3回以上使用すると「応答なし」
- 現象は発生したり、しなかったり
- 1度発生すると以降は確実に発生
- PCの再起動で発生しなくなることがある
- 応答なしになると、以降の処理がまともに動作しない
- sleep()の時間を変えても改善せず
ちなみに当方の場合、sleep()を使用する目的は「定期実行」というよりは「処理の遅延」「待機」が目的になります。
当初、現象が100%発生していたので「何か対策が必要なのだろうな」と考えているときに、再起動で現象が発生しなくなり「ん?とりあえず大丈夫そうか?」となってしまい、そのまま進めると数日後にまた応答なしになるという状況…
100%動かなければもっと早く解決できたのですが。
ちなみに試してたこと
いろいろ調べて「wx.Sleep()」というものを見つけました。
「wxのSleep関数だし、これで解決じゃん!」
と思って意気揚々と試してみましたが、全然ダメでした。wx.MilliSleep()もダメでした。wx.MicroSleep()はUNIX用なので試していません。
調べていると「定期実行したい」という質問に対する回答はいくつか見かけたのですが「処理を遅延させたい」「待機したい」という質問と回答はなかなか見つけられませんでした。
原因
そもそもの原因について以下のような記載がありました。
質問に挙げたコードのように記述しますと、途中のループ処理が抜けるまで
application.MainLoop()
が呼ばれませんので、アプリケーションがまっとうに動作しません。初心者です。sleep文を入れたら、アプリが正常に作動しなくなりました。
application.MainLoop()
はイベントループなどとも呼ばる「ユーザやシステムからのイベントを待ちうけて、イベントの振り分け処理をする関数」ですので、この関数が呼ばれない限り「アプリケーションが応答しません」となってしまいます。
「一時停止して待機」と「イベント駆動型GUIプログラミング」は一緒に使用できません。メインGUIスレッドが何かを待ってブロックされている限り、他のイベントは処理できず、プログラムはフリーズしているように見えます。オプションは、(実際には待機しないことで)「待機」する方法を変更するか、別のスレッドを使用することです。
ある時点でコードを一時停止する
要するに、イベントドリブンのGUIプログラムのメインループで基本的にsleep()は使用できない、メインループは待機させちゃダメということなのでしょう。
対処法・解決策
別スレッドを作成して、その中でSleep()することにしました。
(私がやりたかったことは)それで解決しました。
サンプルコード
大体、以下のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import wx import time from threading import Thread ################################################################################ #sleep()を含めた処理 ################################################################################ def sleep_function(): time.sleep(1) #その他処理 time.sleep(1) #その他処理 time.sleep(1) ################################################################################ #実行ボタンをクリック時の動作 ################################################################################ def run_button_function(event): thread1 = Thread(target=sleep_function) #sleep_function()を別スレッドにして thread1.start() #スレッド開始 ################################################################################ #メイン処理 ################################################################################ if __name__ == '__main__': window = MyApp(0) # wxPythonのGUI Appインスタンスを生成 (= GUI Appを初期化) frame = MyFrame1(None) # フレーム作成(ウィンドウタイトルとウィンドウサイズを指定) panel = wx.Panel(frame, -1) # ボタンやテキストボックスを配置するためのパネルを作成 #コントロール配置等 run_button = wx.Button(panel, wx.ID_ANY, label='実行') #実行ボタンの作成 run_button.Bind(wx.EVT_BUTTON, run_button_function) #実行ボタン押下と関数をひもづける frame.Show() #フレーム表示 window.MainLoop() #イベント待機 |
参考サイト
- 初心者です。sleep文を入れたら、アプリが正常に作動しなくなりました。
- Pause the code at some point
- 【Python入門】初心者に最適!Pythonで簡単なタイマーを作成しよう
- マルチスレッドでwxPython
- wx.Timaer
- wx.Sleep()
- wx.MilliSleep()
- wx.MicroSleep()
以上。
後記
最後までお読みくださりありがとうございます。
こんなに更新したのに、現在はほぼ誰も見ていないゴミカスクズ無価値ブログです。
よければ(はてな)ブックマークや拡散をお願いいたします。
更新の原動力として励ましが欲しいのです…<(_ _)>
ディスカッション
コメント一覧
まだ、コメントがありません