#python #subprocess #system-calls #kill
#python #подпроцесс #системные вызовы #убить
Вопрос:
Есть ли правильный способ создать скрипт, который перебирает файлы в папке и выполняет подпроцесс, который может быть отключен извне с помощью Ctrl C? У меня есть что-то вроде следующего, встроенного в конвейер, и я не могу нажать Ctrl C из командной строки, когда основной процесс остановлен.
Пример скрипта:
import subprocess
import os
import sys
input_directory = sys.argv[1]
for file in os.listdir(os.path.abspath(input_directory)):
output = file "_out.out"
command = ['somescript.py', file, output]
try:
subprocess.check_call(command)
except:
print "Command Failed"
Затем я бы выполнил program:
Example_script.py /path/to/some/directory/containing/files/
Во время выполнения цикла, если я вижу, что команда выполнена с ошибкой, я хочу использовать Ctrl C. Однако он завершается с ошибкой и продолжает запускать дополнительные подпроцессы, несмотря на то, что основной скрипт был уничтожен с помощью Ctrl C. Есть ли правильный способ написать что-то подобное, что может уничтожить дочерние элементы (дополнительный подпроцесс) с помощью Ctrl C?
Любая помощь или указание мне направления очень ценятся. В настоящее время я ищу хороший метод для выполнения.
Комментарии:
1. Почему бы просто не выйти из вашей программы, когда вы перехватываете исключение, после печати «Сбой команды»? — Вы можете усложнить этот процесс, добавив в свой код обработку сигналов, которая вызывается при смерти дочернего процесса, но в этом случае кажется, что вы просто хотите прекратить цикл при сбое. … или вы хотите сказать, что в этом случае вы не получаете исключения?
2. @Steve Я не знаю, почему я еще этого не пробовал. лол, это буквально меня еще не поразило. Спасибо! Если бы я хотел попробовать более сложную обработку сигналов, как бы я это сделал? Буду ли я проверять состояние подпроцесса, когда он вернется?
Ответ №1:
То, что у вас есть в вашем блоке try / except, слишком разрешительно, так что при нажатии Ctrl C KeyboardInterrupt
исключение также обрабатывается тем же обработчиком исключений, что и тот, который print "Command Failed"
, и поскольку это теперь обрабатывается там должным образом, поток программы продолжается через цикл for. Что вам следует сделать, так это:
- Замените
except:
наexcept Exception:
, чтобыKeyboardInterrupt
исключение не было захвачено, так что при любом нажатии Ctrl C программа завершится (включая подпроцессы, которые не застряли в каком-либо не завершаемом состоянии); - После
print
инструкцииbreak
завершите цикл, чтобы предотвратить дальнейшее выполнение, если вы хотите, чтобы эта программа выполняла именно такое поведение.
Комментарии:
1. Спасибо за ваш ответ. Я тоже попробую это сделать. 🙂 Я обязательно отвечу с обновлениями.
Ответ №2:
Вы можете перехватывать KeyboardInterrupt
, таким образом, вы можете обрабатывать Ctrl C любым способом, который вы хотите.
import subprocess
import os
import sys
input_directory = sys.argv[1]
for file in os.listdir(os.path.abspath(input_directory)):
output = file "_out.out"
command = ['somescript.py', file, output]
try:
subprocess.check_call(command)
except KeyboardInterrupt as e:
print "Interrupted"
sys.exit(1)
except:
print "Command Failed"
Однако я согласен с другими постерами в том, что ваше исключение слишком расплывчатое, и вам следует быть более конкретным в том, что может и не может завершиться ошибкой.
Ответ №3:
Я думаю, Ctrl Z также может помочь вам перевести выполнение в фоновый режим и приостановить его.