Найти в Дзене
programmer's notes (python and more)

Программирование на Python. Многозадачность. Модуль subprocess. Отсоединение дочернего процесса

Доброго здоровья читателям моего канала programmer's notes. Поддерживаем мой канал.

Базовый курс программирования на Python | programmer's notes (python and more) | Дзен

Многозадачность и отсоединение дочернего процесса

Я иногда просматриваю свои подборки по тем или иным темам и часто нахожу, что не освящён тот или иной вопрос. Ну и стараюсь возместить пробел. Сегодня опять модуль subprocess, и вопрос, такой: завершение родительского процесса и что происходит с дочерним. И вообще по многозадачности я много чего не договорил. Так что буду ещё к этой теме возвращаться.

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

Рассмотрим такую задачу. Родительская программа запускает дочернюю, которая будет осуществлять рекурсивный поиск по файловой системе, начиная с указанного каталога. Будем ориентироваться на ОС Linux.

Начнём в начале с дочерней программы, над которой и будем осуществлять эксперименты.

Рисунок 1. Программа рекурсивного прохода по файловой системе. Полный текст см. ниже по ссылке
Рисунок 1. Программа рекурсивного прохода по файловой системе. Полный текст см. ниже по ссылке
primer389.py

Программа на рисунке 1 выполняет рекурсивный поиск по каталогам, начиная с указанного. Результат помещается в файл. И имя файла и начальный каталог указываются для неё в качестве параметров родительским процессом. Объяснение алгоритма поиска см. в статье здесь (метод os.walk()). В алгоритме также предусмотрена задержка time.sleep().

Выполним в другой программе строку

proc = subprocess.run(['./p2.py', 'dir.txt', '/bin'])

Особенность метода run() в том, что он ждёт завершения дочернего процесса. Т.е. пока дочерний процесс не поместит все данные в файл и не закрое его, родительский процесс будет ждать. Что здесь интересно. Если нажать Ctrl+C, то родительский процесс закончит работу, соответственно закончит работу и дочерний процесс. Обычные способы удаления процесса, например, с помощью kill или killall убивают только родительский процесс. Чтобы убить родительский процесс вместе с дочерними нужно найти все идентификаторы. Например зная идентификатор родительского процесса, можно получить все идентификаторы дочерних процессов в командной строке (или скрипте на командном языке, например bash) так

ps -o pid= --ppid pid

Но это уже совсем другая история.

В модуле subprocess чаще используют метод Popen(), позволяющий более гибко управлять дочерними процессами. Но если мы просто выполним программу, состоящую из одной строки

proc = subprocess.Popen(['./p2.py', 'dir.txt', '/'])

то родительский процесс закончит свою работу, а дочерний продолжить выполнять свою задачу, до её конца. Т.е. родитель не ожидает конца работы дочернего процесса. Чтобы как-то это отслеживать нужно воспользоваться более тонкими механизмами. Смотрим программу на рисунке 2.

Рисунок 2. Проверка состояния дочернего процесса. Текст см. по ссылке
Рисунок 2. Проверка состояния дочернего процесса. Текст см. по ссылке
primer390.py

Метод poll() возвращает None, если дочерний процесс ещё работает (см. здесь).

Многозадачность в Python | programmer's notes (python and more) | Дзен

Пока всё!

Хорошего программирования. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.

Отпустите ваши дочерние процессы на свободу, они уже взрослые
Отпустите ваши дочерние процессы на свободу, они уже взрослые