Как сразу остановить подпроцесс Python, который запускает модульные тесты?Завершить и убить не работает

StackOverflow https://stackoverflow.com/questions/3302910

Вопрос

У меня есть графический интерфейс Tkinter, в котором выполняются два потока: основной поток для графического интерфейса и рабочий поток.Рабочий поток создает подпроцесс, используя следующий код:

myProcess = subprocess.Popen(['python', '-u', 'runTests.py'],  
                         stdout=subprocess.PIPE, 
                         stderr=subprocess.STDOUT)

Файл runTests.py выполняет некоторую настройку, а затем запускает файл модульного теста с помощью следующей команды:

execfile('myUnitTests.py')

В файле myUnitTests.py содержится несколько модульных тестов, выполнение некоторых из которых занимает более пяти минут.В графическом интерфейсе я нажимаю кнопку, чтобы остановить выполнение тестов.Это, в свою очередь, заставляет рабочий поток отправить сигнал об остановке подпроцесса:

myProcess.terminate()

Команда завершения не останавливает процесс сразу, она ждет, пока текущий модульный тест завершится, а затем завершает процесс?Я пытался использовать os.kill но я получаю те же результаты, что и с terminate().

Есть идеи, как сделать мою программу более отзывчивой, чтобы она сразу убивала подпроцесс?

Это было полезно?

Решение

Документация Python [ http://docs.python.org/library/signal.html ] говорит:

  • Хотя обработчики сигналов Python вызываются асинхронно для пользователя Python, они могут выполняться только между «атомарными» инструкциями интерпретатора Python.Это означает, что сигналы, поступающие во время длительных вычислений, реализованных исключительно на C (например, сопоставление регулярных выражений с большими объемами текста), могут задерживаться на произвольное время.

Итак, если ваш пятиминутный модульный тест выполняет «длинные вычисления, реализованные исключительно на C», и ваша программа модульного тестирования устанавливает обработчик для SIGTERM, это твоя проблема.Если да, попробуйте myProcess.kill вместо myProcess.terminate (или, если у вас нет 2.6, myProcess.send_signal(9)). SIGKILL не перехватывается из пользовательского пространства и должен иметь немедленный эффект.

Предупреждение:любые действия по очистке, которые должны выполняться на выходе из среды модульного тестирования, не будут выполнены.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top