Как можно передать ссылку на экземпляр класса в другие модули, чтобы взаимодействовать с ним?

Добрый день. Есть сайт (точнее панель управления) на Django. При запуске веб-сервера должен запускаться демон (создаваться экземпляр класса, который при инициализации запускает бесконечный цикл в новом потоке. Сейчас это происходит в models.py приложения). В дальнейшем (по запросу пользователя из панели) необходимо передавать/получать данные от этого демона при помощи его методов из обработчика страницы (предположим /save).

Соответственно возникает вопрос: как можно передать ссылку на экземпляр класса (демона) в другие модули (обработчик страницы), чтобы взаимодействовать с ним.

Если это невозможно, то опишите, как бы Вы реализовали подобное. Именно в контексте django.

P.s. Вариант класть нужные данные/запросы/etc в базу данных не предлагать, т.к. вся эта система работает на raspberry pi и SD-карту лишний раз трогать не хочется. Кроме того есть операции, в которых нужна мгновенная реакция от демона.

Заранее благодарю за помощь.
  • Вопрос задан
  • 4325 просмотров
Решения вопроса 2
@hsc
full stack python back-end developer
Не думайте о потоках как об объектах, потому что они ими не являются. Поток — это нить выполнения, которая во время инициализации принимает функцию, которую будет выполнять. После инициализации — это отдельный мини-процесс. Вызвать метод потока невозможно: у него их попросту нет. Можно вызвать метод дескриптора (объекта, который управляет потоком) но не самого потока. Отличием потоков от процессов является то, что потоки разделяют адресное пространство с процессом, который их породил. Это значит, что каждый поток имеет доступ к данным процесса и других потоков.

Теперь о вариантах решения. Я их вижу несколько:
1. Перед запуском потока создать proxy-объект, экземпляр класса, который будет описывать подходящую для вас структуру данных. В зависимости от задачи, может быть полезным посмотреть на Queue, он из коробки потоко-безопасен. После этого просто передать ссылку на этот объект в конструктор потока и общаться через него. Поток пишет в этот объект - django читает из него, и наоборот. Модель очереди для таких задач подходит как нельзя лучше, потому как нельзя гарантировать то, что поток подхватит задачу сразу по ее появлению, и другая задача не затрет предыдущую. Создавать proxy-объект нужно в такой точке, из которой выполнение процесса родителя не выйдет до остановки потока, иначе Вы рискуете потерять контроль над потоком или ловить "странные" ошибки.

2: Если есть необходимость ставить перед потоком разные задачи может быть разумно вынести их хранение во внешние службы, например redis. Он очень быстрый и существенного оверхед даже на малинке не создаст. Общаться с ним можно через этот пакет. Если хотите сэкономить на tcp-трафике - запускайте redis на unix-сокете.
Этот вариант потенциально избавит Вас от головной боли с синхронизацией задач.

3: Если есть возможность и памяти хватает больше чем на 1 поток - RQ. Это — легкий менеджер очереди задач для python. По сути, то, что Вы и пытаетесь реализовать.
Ответ написан
wutiarn
@wutiarn Автор вопроса
В общем, благодаря @hsc задача успешно решена. Демон выносится в отдельный процесс. После этого с ним можно обмениваться данными через Redis. Синхронизируется все это при помощи unix'овых сигналов.

Все гениальное просто.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
EvilsInterrupt
@EvilsInterrupt
System programming, Reversing Engineering, C++
В питоне принято что каждый метод принимает первым параметром передается self. Это и есть ссылка на объект класса.
Ответ написан
@alz
Обычно при деплое django-проекта (достаточно популярны связки apache + mod_wsgi и nginx + uwsgi) запускается несколько процессов, обслуживающих запросы пользователей. У вас будет один процесс, или у вас будет несколько "демонов"? Выносите демона в отдельное приложение и дергайте его через XMLRPC
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы