Форум сайта python.su
Добрый день!
Нужен совет экспертов.
Хочу сделать os.fork() из view, но порожденный процесс приобретает все открытые дескрипторы родителя, в том числе и WSGI-сокет. При попытке прибить все открытые дескрипторы в дочернем процессе получаю ошибку сокета WSGI мол не работает.
Нужно отцепить от django код именно отдельным процессом.
Если более подробно:
def view(request): ... if not os.fork(): target() return def target(*args, **kwargs): ... sd = socket.socket(*args, **kwargs) sd.bind(*args) sd.listen() nsd = sd.accept() ...
Офлайн
Используйте модуль subprocess или mutliprocessing или python-daemon.
Или запускайте второй процесс по крону, например, с помощью pycron.
Или используйте Celery.
Зависит от нюансов задачи.
Отредактировано Lexander (Ноя. 22, 2012 13:46:29)
Офлайн
vvpoloskin
Для запуска дочерних приложений в общих целей предпочтительнее subprocess
subprocess.Popen(...., close_fds=True, ...)
Офлайн
Celery не очен
JOHN_16
vvpoloskinДля запуска дочерних приложений в общих целей предпочтительнее subprocess
Офлайн
Так, уже лучше. Выяснилось, что если делаешь форк на девелоперском сервере, вся дочерний процесс наследует все файловые дескрипторы, а Django при обработке запроса посылает во все эти дескрипторы.
Таким образом даже если из дочернего процесса принудительно закрывать отнаследованные файловые дескрипторы, Django будет пытаться писать в закрытый сокет и все рухнет.
Может быть кто-то меня прокоментирует или поправит?
Офлайн
Ну народ, неужели никто не знает, как тупо сделать fork в Django, чтоб работало на девелоперском сервере?
Офлайн
Тупо сделать форк в Джанго - это не работает.
Потому что это архитектурная ошибка, которую вы допускаете.
Файловые дескрипторы (и сокеты в том числе) не работают напрямую в создаваемом мультипроцессорном окружении. По своей сути. Это эксклюзивно блокируемый ресурс.
Есть простое правило, по которому можно заранее знать (или узнать), что будет работать, а что нет.
Если объект может быть сериализирован с помощью pickle, то его можно передавать между процессами, иначе - он потребует специальной обработки.
Для сокетов, соединений с БД, файлов и т.п.
Примером специальной обработки может быть закрытие и открытие заново соединения.
Поэтому для общения между родительским и дочерним процессом используются очереди и пайпы.
Для их реализации используют удобные системы-обертки типа Celery.
А для управления передачей данных (объектов) используются менеджеры, обеспечивающие эксклюзивный доступ к данным (объектам), следят за их доступностью (сокет открыт/закрыт) и т.п.
Пример
http://dickbrouwer.com/post/32405801335/django-zeromq-and-celery-multiprocessing-gotcha
ЗЫ
Если у вас возникает ошибка
IOError: sys.stdout access restricted by mod_wsgi
обновите mod_wsgi.
Офлайн
Lexander
Файловые дескрипторы (и сокеты в том числе) не работают напрямую в создаваемом мультипроцессорном окружении. По своей сути. Это эксклюзивно блокируемый ресурс.
Есть простое правило, по которому можно заранее знать (или узнать), что будет работать, а что нет.
Если объект может быть сериализирован с помощью pickle, то его можно передавать между процессами, иначе - он потребует специальной обработки.
Для сокетов, соединений с БД, файлов и т.п.
Примером специальной обработки может быть закрытие и открытие заново соединения.
Офлайн
vvpoloskinможно передать рабочую директорию в дочерний процесс, и импортировать модуль.
Popen не проходит, так как хочу запускать не отдельный скрипт, а импортировать функционал из другого модуля.
Офлайн
Хорошо, моя задача состоит в следующем:
из Django мне нужно запускать некоторую внешнюю программу-сервер, которая будет работать некоторое количество времени, конфигурационный файл этой программы создается на основе данных, введенных пользователем в форме. Также вместе с этой программой нужно запускать самописный сокет-сервер, который будет обрабатывать вывод программой.
Хотелось бы запускать внешнюю программу путем fork() и Popen в нем, а также отдельным потоком от вновь порожденного процесса стартовать собственно сокет-сервер.
Офлайн