Полностью переписано на основе моего собственного расследования
У меня есть мастер-скрипт, который запускает ряд других скриптов на Python.
Сценарии создаются как
from subprocess import STDOUT, Popen
from signal import SIGINT
import shlex
p = Popen(shlex.split("python somescript.py arg1 arg2"), cwd="../src/somedir", stderr=STDOUT)
И заканчиваются
p.send_signal(SIGINT)
p.wait()
Внутри них есть следующий код
if __name__ == "__main__":
import signal
def terminate(*args):
raise KeyboardInterrupt
signal.signal(signal.SIGINT, terminate)
# do some work here
Каждый скрипт имеет некоторую функцию, имеющую
try:
# create workers
except KeyboardInterrupt:
# cleanup, wait for the current worker to end, then return
Все описанные работы работают так, как предполагалось - мастер-сценарий создает процессы, когда его выполнение заканчивается, он отправляет им SIGINT, они обрабатывают его правильным образом, изящно завершая работу.
Теперь я хочу запустить сервер разработки Django таким же образом.
Я изменил файл manage.py
:
if __name__ == "__main__":
import signal
def terminate(*args):
print 'got SIGINT'
raise KeyboardInterrupt
signal.signal(signal.SIGINT, terminate)
execute_manager(settings)
Функция execute_manager
после нескольких вызовов приводит к методу команды django, имеющему блок except KeyboardInterrupt
с sys.exit(0)
. Итак, вся установка выглядит одинаково.
Проблема: сервер django фактически не останавливается, хотя я вижу вывод got SIGINT
.
Возможно объяснение:
Похоже, django manage.py разветвляется или делает что-то подобное; заглядывая в Activity Monitor (обозреватель процессов osx), я вижу 3 запущенных процесса на python - один для главного сценария и, возможно, 2 для manage.py. При завершении 2 из них останавливаются (основной сценарий и тот, на который у меня есть ссылка с p
), в то время как третий продолжает блокировать порт 8000.
Есть ли способ получить pids подпроцесса процесса?