Я сейчас пытаюсь написать Python
программу, которая запускает Tkinter
GUI.Одной из особенностей графического интерфейса является то, что он запускает команду оболочки после нажатия кнопки.Для этого я использую модуль subprocess
.
Поскольку выполнение команды оболочки занимает некоторое время, я использую поток, чтобы графический интерфейс не зависал.
Пока все работает,но теперь я хотел бы добавить еще одну кнопку, которая может убить команду оболочки.Если я запускаю команду без моего Python GUI, я просто использую ctrl-c
.Как я могу сделать это в моем графическом интерфейсе, по нажатию кнопки?Я предположил бы, что это довольно распространенная и простая вещь, которую можно сделать, но я просто не нашел ничего, что могло бы работать для меня ...
Вот минимальная версия моего кода:
import subprocess
import Tkinter as tk
from threading import Thread
import signal
class GUI:
def __init__(self,master):
self.master = master
master.title('Program')
#Button to Run command
self.button_idarun = tk.Button(master,text="Run",command=self.Runthread)
self.button_idarun.grid(row = 0, column = 0)
#Button to terminate command
self.button_terminate = tk.Button(master, text = "Stop", command = self.terminate)
self.button_terminate.grid(row = 1, column =0)
#Function that runs command.
def Run(self):
self.p = subprocess.Popen("cd IDA/trunk;./job_sge", stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True)
for line in iter(self.p.stdout.readline,''):
print line
#Function that calls Run in a thread, so other buttons can still be pressed ...
#Probably not the correct way to do this(?)
def Runthread(self):
self.thread = Thread(target=self.Run)
self.thread.start()
#Function that terminates the process started in RUN
#This is the part that does not work.
def terminate(self):
self.p.send_signal(signal.SIGINT)
root = tk.Tk()
gui = GUI(root)
root.mainloop()
Заранее благодарю за любую помощь, которую вы, ребята, можете предложить, и извините за плохое кодирование.Я стараюсь изо всех сил здесь: - /
Редактировать:
Так что теперь я попробовал еще более простую версию своего кода и заменил команду, которую я на самом деле хочу выполнить, простым пингом.Итак, функция Run
теперь выглядит так:
def Run(self):
self.p = subprocess.Popen("ping 8.8.8.8", stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True)
for line in iter(self.p.stdout.readline,''):
print line
С программой Ping моя программа работает без проблем.Когда я нажимаю Run
, он начинает непрерывно пинговать, пока я не нажму Stop
, когда он остановится.
Таким образом, проблема, похоже, является командой ./job_sge
, которую я выполняю.Хотя я не понимаю, почему это будет иметь значение.Если я выполню его непосредственно из оболочки, я могу убить его с помощью ctrl-c
, разве это не то же самое, что делает signal.SIGINT
?
Редактировать 2:
Хорошо, я думаюЯ нашел проблему.По-видимому, это не работает, если вы отправляете две команды одновременно.Например, с приведенной выше командой ping она работает, но когда я дважды нажимаю кнопку «Выполнить», она больше не работает.
То же самое, если я могу изменить команду Run
, например, на
def Run(self):
self.p = subprocess.Popen("cd ..;ping 8.8.8.8", stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True)
for line in iter(self.p.stdout.readline,''):
print line
тогда кнопка остановки больше не работает.
Проблема сейчас в том, что моя команда ./job_sge
- это скрипт bash, который сам выполняет несколько других команд.Поэтому, даже если я изменю cd IDA/trunk;./job_sge
на <Full Path>/job_sge
, я все равно не смогу остановить команду ...