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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

1回答

1162閲覧

Python 端末の閉じるイベントをキャッチしたい

shirasublue

総合スコア19

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

0クリップ

投稿2022/12/28 02:40

実現したいこと

 Windows10 環境にて Python ファイルをダブルクリックして生成される Python 端末ウィンドウ(Pythonロゴが端末の前にあるアイコンの端末)の閉じるボタンイベントをキャッチし、即時終了したいです。

環境

  • Windows 10 21H2 19044, 1620
  • Python 3.9.5 (embeddable python)

発生している問題

 Python 端末の閉じるボタンから閉じると固まってしまいます。

 GUI は、Python から multiprocessing にて matplotlib のアニメーションウィンドウを開き、2窓が同時並行して動く構成になっています。

 また、バックグラウンド用にもう1プロセス multiprocessing で動かしています。

 matplotlib の閉じるイベントはキャッチでき、また Pythonウィンドウも KeyboardInterrupt もキャッチできているため、ウィンドウに合わせて Ctrl+C を押下したり、matplotlib の閉じるボタンでは即時終了します。

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

 以下のメッセージが発生しているところを捉えました。
出るかどうかはまちまちです。出ないときはすぐに終了します。
閉じるボタンを押した時点で Windows の画面としては見えなくなるようで
スクショできませんでしたが、カメラで撮ることができました。

Python3

1QObject::~QObject: Timers cannot be stopped from another thread

ソースコード

Python

1import time 2from collections import deque 3from ctypes import * 4from multiprocessing import Array, Process, Queue, freeze_support 5 6import _queue 7import matplotlib.pyplot as plt 8import numpy as np 9 10N = 100 11Q_TIMEOUT = 1 12 13def sampling(sig, q): 14 i = 0 15 16 while True: 17 if not sig.empty(): 18 break 19 20 x = np.linspace(i, i + 2.0 * np.pi, N) 21 y = np.sin(x) 22 23 q.put(y) 24 25 i += 0.001 26 27 28def on_close(event, sig): 29 sig.put(True) 30 31 32def viewer(sig, data_array): 33 plt.ion() 34 35 fig = plt.figure() 36 fig.canvas.mpl_connect( 37 'close_event', lambda event: on_close(event, sig)) 38 39 n = np.linspace(-N, 0, N) 40 y_init = np.ones(N) 41 42 ax = fig.add_subplot(111,) 43 line, = ax.plot(n, y_init,) 44 45 ax.set_ylim([-1.2, 1.2]) 46 47 while True: 48 if not sig.empty(): 49 break 50 51 y = np.array(data_array[0]) 52 53 line.set_ydata(y) 54 55 fig.canvas.blit(ax.bbox) 56 fig.canvas.flush_events() 57 58 59def main(): 60 freeze_support() 61 62 sig = Queue() 63 q = Queue() 64 65 sampler = Process( 66 target=sampling, 67 args=(sig, q,), 68 ) 69 sampler.start() 70 71 data_array = [Array(c_double, range(N))] 72 display = Process( 73 target=viewer, 74 args=(sig, data_array,), 75 ) 76 display.start() 77 78 try: 79 while sampler.is_alive() and display.is_alive(): 80 if not sig.empty(): 81 break 82 83 y = q.get(timeout=Q_TIMEOUT) 84 data_array[0][:] = y 85 86 except KeyboardInterrupt: 87 sig.put(True) 88 89 except _queue.Empty: 90 sig.put(True) 91 92 sig.put(True) 93 display.join() 94 sampler.join() 95 96 97if __name__ == '__main__': 98 main() 99

試したこと

 .pyw にすると見えなくなりますが、同時に端末で数値を確認できなくなるためやりたくありません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

本来であれば適切に終了処理を実施するべきなので、質問にあるようにイベントを捕捉できるのであればそれがいいのですが、次善の策のコメントです。

multiprocessingの子プロセスは、生成時のdaemon引数にTrueを渡すと、親プロセスが停止したときに、一緒に停止するようになります。
https://docs.python.org/ja/3/library/multiprocessing.html#process-and-exceptions
https://docs.python.org/ja/3/library/multiprocessing.html#multiprocessing.Process.daemon

python

1 sampler = Process( 2 target=sampling, 3 args=(sig, q,), 4 daemon=True 5 )

投稿2022/12/28 04:25

編集2022/12/28 06:43
TakaiY

総合スコア12743

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問