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

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

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

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

Q&A

解決済

4回答

5260閲覧

Pythonでサブプロセスのウインドウの停止ボタンを押したらメインプロセスを停止するようにしたい。

Aki1000

総合スコア78

Python 3.x

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

0グッド

0クリップ

投稿2018/11/01 08:33

編集2018/11/01 08:34

GUI作ったこと無いです。よろしくお願いします。

Pythonでメインプログラム実行中に、停止ボタンのついたウインドウを表示させておき、停止ボタンが押されたらプログラムが停止するようにしたいです。

メインのプログラム中に、
subprocess.Popen(['python', 'GUIwindow.py'])
とやっておいて、GUIwindow.pyにtkinterでウインドウを作成するコードを入れて置ければ、メインプロセス実行中にボタンのついたウインドウをう作っておくことはできるみたいなのですが、サブプロセスのボタンが押されたらメインも停止させる方法が分かりません。
サブプロセスのウインドウだけ停止するならボタンの動作に
button3 = tkinter.Button(root, text='Exit', command=sys.exit)
としておけば、消えるのですが、これを押すとメインのプロセスも停止するようにしたいです。どうやれば良いのでしょう?

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

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

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

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

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

guest

回答4

0

ベストアンサー

python

1import tkinter 2import os, signal 3 4def func1(): 5 label.configure(text='button1 pressed') 6 7root = tkinter.Tk() 8label = tkinter.Label(root, text='press button') 9label.pack() 10button1 = tkinter.Button(root, text='Exit', command=lambda: os.kill(os.getppid(), signal.SIGTERM)) 11 12button1.pack() 13root.mainloop()

コメントのコードを改修しました。
このように、os.kill()をlambda式のなかで実行するようにしましょう。
オリジナルのコードではos.killがボタンを作成する段階で評価されてしまいます。
もっと単純にするなら、スレッドを使ってやる方法もありますよ。スレッドのほうがサブプロセスよりは軽量なのでおすすめですね。
サブプロセスは膨大な計算を並列化するときなど、PythonのGILが邪魔なとき、Python以外のプロセスを動かしたいときの手段です。

python

1import tkinter 2from threading import Thread 3 4def submain(): 5 """本来のメインプロセス動作""" 6 7root = tkinter.Tk() 8label = tkinter.Label(root, text='press button') 9label.pack() 10button1 = tkinter.Button(root, text='Exit', command=root.destroy) 11 12th = Thread(target=submain) 13th.start() 14 15button1.pack() 16root.mainloop()

投稿2018/11/01 23:23

編集2018/11/01 23:36
frodo821

総合スコア322

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

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

Aki1000

2018/11/02 10:21

ありがとうございます! 取りあえず、一つ目のos.kill()をlambda式の中で動かす方式で、サブプロセスの窓のボタンから終了させることは出来るようになりました。 一応これで動作はするのですが、もし宜しければ後ろのthreadingの方のコードで、もう少し教えて頂ければありがたいです。こちらの方がスマートな方式に見えるので…… threadingを使うことにより、メインのコードを流しながら、ボタン付きのtkinterのウインドウを表示することは出来ています。しかしながら、こちらのExitボタンを押しても停止するのはtkinterのウインドウだけで、メインのプロセスは動作し続けてしまいます。 button1 = tkinter.Button(root, text='Exit', command=root.destroy) のcommandをroot.destroy以外の何かにすることで、メインのプロセス(submain)が停止するようには出来ないでしょうか?
frodo821

2018/11/02 10:31

threadingモジュールのEventを使って終了監視するくらいしかないと思います…。 残念ながらPythonのスレッドには割り込みが存在しないんですよね…。 evt = Event() としておいて、submain()のなかでループの先頭に evt.is_set()判定を置いとくくらいしかないですね…。 root.destoryをlambda: (root.destory(), evt.set())とすればループを抜けることはできます。
guest

0

python

1import os, signal 2os.kill(os.getppid(), signal.SIGTERM)

投稿2018/11/01 08:53

YouheiSakurai

総合スコア6142

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

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

Aki1000

2018/11/01 17:24

回答ありがとうございます……けど、うまくいかないです。 サブプロセスのpyファイルを import tkinter import os, signal def func1(): label.configure(text='button1 pressed') root = tkinter.Tk() label = tkinter.Label(root, text='press button') label.pack() button1 = tkinter.Button(root, text='Exit', command=os.kill(os.getppid(), signal.SIGTERM)) button1.pack() root.mainloop() として、これをsubprocess.Popenでメインプロセスのpyファイルから開くと、このサブプロセスの作るwindowが開いて、その瞬間メインが閉じます。ボタンを押さないでも勝手にメインが終了してしまいます。
guest

0

subprocess.Popenではなく、multiprocessingのProcessという命令を使うことで一つのpyファイル内で実現することが出来ました!
もしかするとthreadingでもう少し安全にうまくやる方法もあるのかも知れませんが、今のところ精一杯綺麗に実現した方法ということで。

python

1#coding:utf-8 2from multiprocessing import Process 3from time import sleep 4import tkinter 5import os, signal 6 7 8 9def func1(): 10 root = tkinter.Tk() 11 label = tkinter.Label(root, text='press button') 12 label.pack() 13 button1 = tkinter.Button(root, text='Exit', command=lambda: os.kill(os.getppid(), signal.SIGTERM)) 14 button1.pack() 15 root.mainloop() 16 17 18def main(): 19 i = Process (target=func1) 20 i.start() 21 j=0 22 while True: 23 #メイン処理省略 24 print("target.JPG",j) 25 j+=1 26 sleep(1) 27 28if __name__ == "__main__": 29 main() 30 31 32

投稿2018/11/04 00:37

編集2018/11/04 00:58
Aki1000

総合スコア78

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

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

0

なぜメインの方で全てやらないのかよくわかりませんが、
subprocess.Popen
を行う際にでも、プロセス間通信を行うようにして、その結果を持って終了するようにするとか。

subprocess.Popenではpipeが使えるので、これで起動した時に標準出力にfinishとか出力し、
メイン側ではそのpipeを監視、finishで終了する、など。

投稿2018/11/01 11:31

t_obara

総合スコア5488

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

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

Aki1000

2018/11/01 15:19 編集

ありがとう御座います。 メインの方で全て出来るやり方を教えて頂けるとさらにありがたいのですが、メインの方でtkinterでウインドウを作ると、ウインドウを表示する処置が終わるまで他の処理が出来ないといいますか…… 長々とメインのpyファイルを書いて、途中でその停止ボタンを表示させたいと思う部分で import tkinter import sys def func1(): label.configure(text='button1 pressed') root = tkinter.Tk() label = tkinter.Label(root, text='press button') label.pack() button1 = tkinter.Button(root, text='Exit', command=sys.exit) button1.pack() root.mainloop() とやると、メインのプログラムがそのウインドウを消すまで止まっているといいますか……… そこから先が走らないです。根本的に何か作り方がよく分かってない感じです。 なのでメインプログラムを走らせて停止ボタン出すには途中でこういうのをsubprocess.Popenで開けばいいのかなと苦肉の策を。 ウインドウを出しつつメインのプロセスを走らせるのをメインだけでやるにはどうしたら良いんでしょう?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問