2010-12-29 4 views
2

Полностью переписан на основе моего собственного исследованияНагрузочный подпроцесс в Python

У меня есть мастер-скрипт, который запускает ряд других сценариев 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 dev таким же образом.

Я изменил 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 функции после того, как количество вызовов, приводит к способу команды Джанго, имеющему except KeyboardInterrupt блока с sys.exit(0). Таким образом, вся установка выглядит одинаково.

Проблема: сервер django на самом деле не остановлен, хотя я вижу вывод got SIGINT.

Возможно объяснение:

Похоже, сама Джанго manage.py вилок, или делает что-то подобное; глядя в Activity Monitor (проводник процессов osx). Я вижу, что запущено 3 процесса python - одно для мастер-скрипта и, возможно, 2 для manage.py. Когда заканчивается, 2 из них останавливаются (мастер-скрипт и тот, с которым у меня есть ссылка с p), в то время как третий продолжает блокировать порт 8000. Есть ли способ получить подпроцессы процесса?

+1

Почему вы не используете 'p.kill()'? –

+0

, потому что подпроцессы имеют определенную структуру, каждая из которых имеет свой обработчик для KeyboardInterrupt и делает выход __gracefull__ (например, ожидающий завершения рабочих заданий) – Guard

+0

Какая ОС вы используете? – mjhm

ответ

0

Вы можете использовать psutil, чтобы узнать о дочерних процессах, например. в псевдокоде:

p = Popen(...) 
pp = psutil.Process(p.pid) 
for child in pp.get_children(): 
    child.send_signal(signal.SIGINT) 

Обратите внимание на разницу в процессах при работе без --reload, полученные с использованием ps -ef | grep manage.py | grep -v grep:

vinay 7864 7795 9 22:10 pts/0 00:00:00 python ./manage.py runserver 
vinay 7865 7864 16 22:10 pts/0 00:00:00 /usr/bin/python ./manage.py runserver 

по сравнению с использованием опции --noreload:

vinay 7874 7795 7 22:10 pts/0 00:00:00 python ./manage.py runserver --noreload 
+0

да, я уже замечаю разницу, хотя не знаю, как получить список дочерних процессов. спасибо, это помогло. – Guard

Смежные вопросы