- Как завершить процесс из Python, используя pid?
- 2 ответа
- Python. Урок 24. Потоки и процессы в Python. Часть 3. Управление процессами
- Процессы в Python
- Класс Process
- Создание и ожидание завершения работы процессов
- Создание классов-наследников от Process
- Принудительное завершение работы процессов
- Процессы-демоны
- P.S.
- Как убить процесс и дочерние процессы из Python?
- 5 ответов
- Как завершить скрипт Python
- Как убить процесс Popen(‘start’, shell=True)
- 3 ответа 3
Как завершить процесс из Python, используя pid?
Я пытаюсь написать короткий script в python, который запустит еще один код python в подпроцессе, если еще не запущен другой конец терминала и приложения (Linux).
У вас возникли проблемы с отсутствием знаний, чтобы назвать процессы pid, которое приложение читает из файла «.proc». Другая проблема заключается в том, что интерпретатор говорит, что строка с именем dat не равна «x». Что я пропустил?
2 ответа
Использование awesome psutil библиотека довольно проста:
Если вы не хотите устанавливать новую библиотеку, вы можете использовать модуль os :
Если вы заинтересованы в запуске команды python StripCore.py , если она не запущена и в противном случае убивает ее, вы можете использовать psutil , чтобы сделать это надежно.
Примечание. В предыдущих версиях psutil cmdline был атрибутом вместо метода.
Я хотел сделать то же самое, что и я, но я хотел сделать это в одном файле.
Таким образом, логика будет:
- если script с моим именем запущен, убейте его, а затем выйдите из
- если script с моим именем не запущено, делайте что-нибудь.
Я изменил ответ Бакуриу и придумал следующее:
Запуск script сделает все, что делает script. Запуск другого экземпляра script приведет к уничтожению любого существующего экземпляра script.
Я использую это для отображения небольшого виджета календаря PyGTK, который запускается, когда я нажимаю часы. Если я нажму, и календарь не будет открыт, отобразится календарь. Если календарь запущен и я нажимаю часы, календарь исчезает.
Python. Урок 24. Потоки и процессы в Python. Часть 3. Управление процессами
Продолжаем изучать параллельное программирование на Python. На этот раз разберемся с тем как создавать процессы, управлять завершением их работы и изучим особенности процессов-демонов.
Процессы в Python
Процессы в Python позволяют запустить выполнение нескольких задач в параллельном режиме. По сути, при старте процесса запускает еще одна копия интерпретатора Python , в котором выполняется указанная функция. Таким образом, если мы запустим пять процессов, то будет запущено пять отдельных интерпретаторов, в этом случае уже не будет проблем с GIL . Такой способ позволяет параллельно запускать задачи активно использующие CPU . Они будут распределяться между несколькими процессами (ядрами), что значительно увеличит производительность вычислений.
Класс Process
Классом, который отвечает за создание и управление процессами является Process из пакета multiprocessing . Он совместим по сигнатурам методов и конструктора с threading . Thread , это сделано для более простого перехода от многопотокового приложения к многопроцессному. Помимо одноименных с Thread методов, класс Process дополнительно предоставляет ряд своих. Познакомимся поближе с этим классом, конструктор класса выглядит следующим образом:
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs=<>, *, daemon=None)
- group
- Параметр всегда равен None , используется для обратной совместимости с Thread .
- target
- Сallable -объект, который будет вызван методом run() при старте процесса.
- name
- Имя процесса.
- args
- kwargs
- Параметры объекта, переданного через target .
- daemon
- Флаг, определяющий является ли данный процесс демоном ( True ) или нет ( False ). Если значение не задано, то оно будет равно свойству daemon родительского процесса.
Помимо методов и свойств, которые совпадают по назначению с аналогичными для класса Thread , класс Process имеет ряд уникальных:
- pid
- Возвращает ID процесса. Если процесс ещё не запущен, то вернет None .
- exitcode
- Код возврата. Если процесс ещё не завершил свою работу, то вернет None .
- authkey
- Ключ аутентификации процесса. При инициализации multiprocessing, с главным процессом связывается специальная строка, которая генерируется с помощью os.urandom() . Это значение наследуют процессы-потомки, но его можно изменить, задав новое значение, через данное свойство.
- sentinel
- Числовой идентификатор, который может использоваться для синхронизации. Подробно об этом будет написано в одном из следующих уроков.
- close()
- Освобождает все ресурсы, связанные с процессом. Если процесс еще работает, то вызов метода приведет к выбросу исключения ValueError .
Создание и ожидание завершения работы процессов
Как уже было сказано выше, за организацию работы с процессами в Python отвечает класс Process . Для запуска процесса используется метод start() . Разберем простой пример:
В рамках данного примера мы написали функцию (строка 4), которая будет выполнена в отдельном процессе, в главном процессе мы создали переменную типа Process (строка 10) с указанием функции func , и запустили его (срока 11). В результате в консоли будут выведены два сообщения из родительского и дочернего процессов:
За ожидание завершения работы процесса(ов) отвечает метод join , со следующей сигнатурой:
При вывозе метода join() выполнение программы будет остановлено до тех пор пока соответствующий процесс не завершит работу. Параметр timeout отвечает за время ожидания завершения работы процесса, если указанное время прошло, а процесс еще не завершился, то ожидание будет прервано и выполнение программы продолжится дальше. В случае, если метод join() завершился по таймауту или в результате того, что процесс был завершен аварийно (терминирован), то он вернет None .
Если в приведенном выше примере код главного процесса заменить на следующий:
То в консоли сообщения будут выведены в таком порядке:
Это происходит потому, что строка print(“Goodbye”) из основного процесса выполняется раньше, чем print(“Hello from child Process”) из дочернего. Для того, чтобы все было выведено в нужном порядке, воспользуемся методом join() :
Для проверки того выполняется процесс сейчас или нет используется метод is_alive() . Дополним наш пример соответствующими проверками:
Создание классов-наследников от Process
В классе наследнике от Process необходимо переопределить метод run() для того, чтобы он (класс) соответствовал протоколу работы с процессами. Ниже представлен пример с реализацией этого подхода.
Мы создали класс CustomProcess , который является наследником от Process и переопределили метод run() , так, что он выводит заданное количество сообщений, которое задается при создании объекта, с интервалом в 500 мс. Запуск процесса осуществляется с помощью метода start() .
Принудительное завершение работы процессов
В отличии от потоков, работу процессов можно принудительно завершить, для этого класс Process предоставляет набор методов:
- terminate()
- Принудительно завершает работу процесса. В Unix отправляется команда SIGTERM , в Windows используется функция TerminateProcess() .
- kill()
- Метод аналогичный terminate() по функционалу, только вместо SIGTERM в Unix будет отправлена команда SIGKILL .
Процессы-демоны
Процессы демоны по своим свойствам похожи на потоки-демоны, их суть заключается в том, что они завершают свою работу, если завершился родительский процесс.
Указание на то, что процесс является демоном должно быть сделано до его запуска (до вызова метода start()) . Для демонического процесса запрещено самостоятельно создавать дочерние процессы. Эти процессы не являются демонами (сервисами) в понимании Unix , единственное их свойство – это завершение работы вместе с родительским процессом.
Указать на то, что процесс является демоном можно при создании экземпляра класса через аргумент daemon , либо после создания через свойство daemon .
При запуске данной программы на консоли должно появиться следующее:
P.S.
Вводные уроки по “Линейной алгебре на Python” вы можете найти соответствующей странице нашего сайта . Все уроки по этой теме собраны в книге “Линейная алгебра на Python”.
Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. Для начала вы можете познакомиться с вводными уроками. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
Как убить процесс и дочерние процессы из Python?
Например из bash:
os.kill(pid, signal.SIGKILL) убить только родительский процесс.
5 ответов
Когда вы передаете отрицательный PID kill , он фактически отправляет сигнал процессу group по этому (абсолютному) номеру. Вы делаете эквивалент с os.killpg() в Python.
Другое решение, если ваш процесс не является группой процессов и вы не хотите использовать psutil , это выполнить команду оболочки:
Ни один из ответов не помог мне, поэтому я провел небольшое исследование и написал свой ответ: Вы можете легко сделать это, используя модуль os , но он чувствителен к платформе. Это означает, что некоторые команды доступны только в Unix, некоторые — на любой платформе. Поэтому мой проект запускает один процесс и несколько дочерних процессов в разных местах и времени. Some of Child запускает процессы Grand-Child 🙂 Итак, я нашел это решение:
Я использую SIGKILL в Linux, чтобы немедленно завершить процесс, и SIGTERM в Windows, потому что там нет SIGKILL . Также я использовал killpg() для уничтожения всей группы процессов в Linux.
Постскриптум Проверьте в Linux, но все еще не проверяете в Windows, поэтому, возможно, нам понадобится еще одна дополнительная команда для Windows (например, CTRL_C_EVENT или используйте другой ответ ).
Если родительский процесс не является «группой процессов», но вы хотите уничтожить его с помощью детей, вы можете использовать psutil (https://pythonhosted.org/psutil/#processes ) . os.killpg не может идентифицировать pid группы, не относящейся к процессу.
Вы должны использовать параметр сигнала 9, чтобы убить дерево процессов.
Как завершить скрипт Python
Мне известна die() команда в PHP, которая рано выходит из скрипта.
Как я могу сделать это в Python?
Выход из Python. Это реализуется путем вызова SystemExit исключения, поэтому действия по очистке, указанные в предложениях finally, try выполняются, и можно перехватить попытку выхода на внешнем уровне.
Необязательный аргумент arg может быть целым числом, указывающим статус выхода (по умолчанию равен нулю), или объектом другого типа. Если это целое число, ноль считается «успешным завершением», а любое ненулевое значение считается «ненормальным завершением» в оболочках и т.п. Большинство систем требуют, чтобы он находился в диапазоне 0-127, и в противном случае дают неопределенные результаты. В некоторых системах есть соглашение о назначении определенных значений определенным кодам выхода, но они обычно недостаточно развиты; Программы Unix обычно используют 2 для ошибок синтаксиса командной строки и 1 для всех других видов ошибок. Если передается объект другого типа, None эквивалентен пропусканию нуля, а любой другой объект печатается в stderr и приводит к коду выхода 1. В частности, sys.exit(«some error message») быстрый способ выхода из программы при возникновении ошибки.
Поскольку в exit() конечном итоге «only» вызывает исключение, оно будет выходить из процесса только при вызове из основного потока, и исключение не перехватывается.
Обратите внимание, что это «хороший» способ выхода. @ glyphtwistedmatrix ниже указывает на то, что если вы хотите «жесткий выход», вы можете использовать его os._exit(*errorcode*) , хотя он, вероятно, в некоторой степени специфичен для ОС (например, он может не принимать код ошибки в Windows) и определенно менее дружественен, так как не позволяет переводчику выполнять очистку до того, как процесс завершится.
Как убить процесс Popen(‘start’, shell=True)
Привет! Создаю процесс в питоне
Но вот убить его из кода не получается. Перепробовал несколько вариантов, но консоль не закрывается
3 ответа 3
Методы .terminate() , .kill() у subprocess.Popen пытаются остановить только сам процесс:
При этом дочерние процессы могут продолжать жить, пример.
Вызвав Popen() с shell=True параметром, создаётся неявно процесс ( cmd.exe , /bin/sh ), который запускает переданную команду. Если это не встроенная/внутренняя команда, то у вас как минимум два процесса получается (сама оболочка плюс программа, которую она запустила). .kill() убивает саму оболочку, при этом дочерний процесс может продолжить жить. На *nix в этом случае можно попробовать запускать процесс в отдельной группе процессов и затем послать сигнал этой группе, чтобы все процессы завершились (похоже на то как Ctrl+C в баше работает): How to terminate a python subprocess launched with shell=True. На Windows, можно taskkill попробовать:
/T аргумент говорит, что taskkill пытается убить как сам процесс так и любые дочерние процессы, которые он запустил. Используя /IM параметр, можно по имени процессы остановить.
Чтобы закрыть новое окно, созданное start командой, по завершению дочерней команды, можно явно /c параметр передать для cmd :
Можно добавить /B к start , чтобы не создавалось новое окно. Если вы использовали start, чтобы в фоне, что-то выполнить, то в Питоне этого не нужно, просто уберите start ( Popen() вызов не ждёт пока процесс завершится). Аналогично, если вам не нужно внутреннюю команду запустить, то можно без shell=True обойтись как правило.
В качестве альтернативы явной остановки, можно запустить процессы таким образом, чтобы дочерние процессы автоматически уничтожались, когда родитель завершается: Python: how to kill child process(es) when parent dies? На Windows, это можно организовать присваиванием созданного родительского процесса к своему Job объекту.