Уничтожение команды оболочки началось с tkinter - PullRequest
0 голосов
/ 25 сентября 2018

Я сейчас пытаюсь написать 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, я все равно не смогу остановить команду ...

1 Ответ

0 голосов
/ 28 сентября 2018

Хорошо, поэтому, выяснив, в чем же заключается проблема, я нашел ответ на StackOverflow:

Как завершить подпроцесс python, запущенный с shell = True

Мне нужно было добавить preexec_fn=os.setsid к моей команде subprocess.Popen и изменить функцию terminate на

def terminate(self):
    os.killpg(os.getpgid(self.p.pid),signal.SIGKILL)

Таким образом, в основном, я объединяю все команды в одну группу команд иубей их сразу.Если я делаю это так, это работает для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...