Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 22, 2012 12:51:56

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Добрый день!
Нужен совет экспертов.
Хочу сделать 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()
  ...



Офлайн

#2 Ноя. 22, 2012 13:39:31

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Django и несколько процессов

Используйте модуль subprocess или mutliprocessing или python-daemon.
Или запускайте второй процесс по крону, например, с помощью pycron.
Или используйте Celery.

Зависит от нюансов задачи.



Отредактировано Lexander (Ноя. 22, 2012 13:46:29)

Офлайн

#3 Ноя. 22, 2012 23:23:47

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Django и несколько процессов

vvpoloskin
Для запуска дочерних приложений в общих целей предпочтительнее subprocess

subprocess.Popen(...., close_fds=True, ...)
Если аргументу close_fds присвоено значение True, то все дескрипторы, исключая 0, 1 и 2 будут закрыты перед выполнением дочернего процесса (только для UNIX).

Однако не факт что для вашей задачи это подойдет. Если не выйдет, присмотритесь к сообщению Lexander



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#4 Ноя. 23, 2012 09:19:45

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Celery не очен

JOHN_16
vvpoloskinДля запуска дочерних приложений в общих целей предпочтительнее subprocess

Popen не проходит, так как хочу запускать не отдельный скрипт, а импортировать функционал из другого модуля.
Может быть кто знает, как в multiprocessing задать опцию, аналогичную close_fds=True в subprocess?



Офлайн

#5 Ноя. 26, 2012 11:13:55

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Так, уже лучше. Выяснилось, что если делаешь форк на девелоперском сервере, вся дочерний процесс наследует все файловые дескрипторы, а Django при обработке запроса посылает во все эти дескрипторы.
Таким образом даже если из дочернего процесса принудительно закрывать отнаследованные файловые дескрипторы, Django будет пытаться писать в закрытый сокет и все рухнет.

Может быть кто-то меня прокоментирует или поправит?



Офлайн

#6 Ноя. 26, 2012 12:31:16

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Ну народ, неужели никто не знает, как тупо сделать fork в Django, чтоб работало на девелоперском сервере?



Офлайн

#7 Ноя. 26, 2012 19:38:06

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Django и несколько процессов

Тупо сделать форк в Джанго - это не работает.
Потому что это архитектурная ошибка, которую вы допускаете.

Файловые дескрипторы (и сокеты в том числе) не работают напрямую в создаваемом мультипроцессорном окружении. По своей сути. Это эксклюзивно блокируемый ресурс.
Есть простое правило, по которому можно заранее знать (или узнать), что будет работать, а что нет.
Если объект может быть сериализирован с помощью pickle, то его можно передавать между процессами, иначе - он потребует специальной обработки.
Для сокетов, соединений с БД, файлов и т.п.
Примером специальной обработки может быть закрытие и открытие заново соединения.

Поэтому для общения между родительским и дочерним процессом используются очереди и пайпы.
Для их реализации используют удобные системы-обертки типа Celery.
А для управления передачей данных (объектов) используются менеджеры, обеспечивающие эксклюзивный доступ к данным (объектам), следят за их доступностью (сокет открыт/закрыт) и т.п.

Пример
http://dickbrouwer.com/post/32405801335/django-zeromq-and-celery-multiprocessing-gotcha

ЗЫ
Если у вас возникает ошибка
IOError: sys.stdout access restricted by mod_wsgi
обновите mod_wsgi.



Офлайн

#8 Ноя. 27, 2012 07:21:22

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Lexander
Файловые дескрипторы (и сокеты в том числе) не работают напрямую в создаваемом мультипроцессорном окружении. По своей сути. Это эксклюзивно блокируемый ресурс.
Есть простое правило, по которому можно заранее знать (или узнать), что будет работать, а что нет.
Если объект может быть сериализирован с помощью pickle, то его можно передавать между процессами, иначе - он потребует специальной обработки.
Для сокетов, соединений с БД, файлов и т.п.
Примером специальной обработки может быть закрытие и открытие заново соединения.

Супер, но мне не нужно использовать ни сокеты, ни открытые файловые дескрипторы в дочернем процессе. Не нужно вообще ничего из этого. Просто если я делаю os.fork() и далее свой код - получаю Port 8000 already in use, что в полне логично. Если я в потомке делаю что-то вроде os.closerange(3, 1024), получаю WSGI-error Bad file descriptor и страница при загрузке бесконечно долго висит, пока не остановишь загрузку в браузере. Как-нибудь это побороть все же можно?



Офлайн

#9 Ноя. 27, 2012 09:27:52

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Django и несколько процессов

vvpoloskin
Popen не проходит, так как хочу запускать не отдельный скрипт, а импортировать функционал из другого модуля.
можно передать рабочую директорию в дочерний процесс, и импортировать модуль.
А вообще помоему уже нужно более открыто говорить о поставленной задаче, а то складывается впечатление что задача у вас поставленна некорректно.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#10 Ноя. 27, 2012 12:35:54

vvpoloskin
От:
Зарегистрирован: 2011-09-02
Сообщения: 31
Репутация: +  0  -
Профиль   Отправить e-mail  

Django и несколько процессов

Хорошо, моя задача состоит в следующем:
из Django мне нужно запускать некоторую внешнюю программу-сервер, которая будет работать некоторое количество времени, конфигурационный файл этой программы создается на основе данных, введенных пользователем в форме. Также вместе с этой программой нужно запускать самописный сокет-сервер, который будет обрабатывать вывод программой.

Хотелось бы запускать внешнюю программу путем fork() и Popen в нем, а также отдельным потоком от вновь порожденного процесса стартовать собственно сокет-сервер.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version