Как лучше организовать два потока исполнения внутри Flask?
Приветствую.
Обдумываю структуру простого мониторинга с графическим интерфейсом. Он должен брать JSON со специально обученного URL-а, проверять некоторые поля и, при совпадении ряда условий, показывать Большой Страшный Красный Прямоугольник, чтобы суппорт пугался и поднимал панику.
GUI хочу сделать на Flask. Но надо ещё решить задачу регулярного подёргивания упомянутого кончика API. Для простоты разворачивая (и сворачивания) не хотел бы использовать cron, поэтому думаю, как бы реализовать это силами всего одного скрипта.
Первый вариант, пришедший в голову — это создать ещё один поток внутри процесса Flask, спать его минут по 5—10, потом обновлять данные. Вроде, неплохая идея, но столкнулся с тем, что пока плохо понимаю устройство фреймворка и не соображу, куда ему этот поток присунуть.
Второй вариант — использовать SIGALARM. Плюс в простой реализации, но нужен совет, как это делается цивильно. Я думаю, реализовать оба поведения (GUI и получение данных) в одном скрипте, а выбор поведения сделать через аргумент. То есть, GUI будет порождать «воркера».
Собственно, вопросы в том, есть ли третий[, четвёртый, пятый...] вариант, насколько плохи предложенные два, и можно ли таки вылепить из них конфетку.
UPD. Да, если кто-то сможет на пальцах объяснить, как воплотить первый вариант, буду безмерно благодарен.
Думаю правильнее и полезнее всего использовать асинхронную очередь заданий, типа Celery (github) или RQ (github).
Во-первых, не придется изобретать велосипед. Во-вторых: ознакомитесь с работой передовых инструментов в этой сфере.
От себя добавлю, что, используя Celery, вы легко и удобно сможете повесить обработчики на задачи. К примеру, после успешного получения json'а, вы можете запустить другой скрипт. Если url с json'ом не доступен, вы сможете задать кол-во попыток "достучаться" до данного url'а. А если задача упадет, то вы можете отправить себе email или написать сообщение в вк или твиттере.
Если я правильно понял, и вам надо сделать некий скрипт демон который с одной стороны предоставляет http интерфейс, а с другой дёргает разные api-ки, и что то ещё по расписанию делает, то посмотрите в сторону asyncio и библиотек на его основе:
У Flask один основной поток, и заставить его проверять там что-то кроме пришедших http-запросов можно конечно, но это путь к переписыванию самого Flask.
Простой путь - независимый от Flask скрипт, который запускается, неважно чем, по расписанию и делает проверку.
Сложный путь - написать себе свой комбайн.
UPD: попробовал отделить процесс Flask в отдельный поток, и к моему удивлению, оно заработало) Код ниже в коментах.
А разве я не могу, допустим, создать потомка от Flask и переписать ему __init__, где буду вызывать родительский __init__, после чего своему классу создавать поле с экземпляром класса Thread?
Можно конечно, о том и речь. Но насколько я вижу, с учетом того что сам Flask не использовал, переписывать надо будет Flask().run(), а не какие-то поля в самом экземпляре приложения.
, и к моему удивлению, оно заработало)
Даже не знаю, решился бы я применить это где-то на практике, или нет)
Проблема на мой взгляд должна возникнуть с тем, что поток Flask'а не должен был отпускать управление потоком, но видимо внутри него где-то есть sleep(), или что-то схожее.
Илья: спасибище! Даже с кодом! :-) Точно, сам я не догадался запихнуть Flask в отдельный поток, я пытался внутри него что-то вертеть. Скорее, внутри у него не sleep, а ожидание соединения на сокете.
Во-первых, есть академический интерес. Задача не срочная и есть время позаморачиваться. Во-вторых, использование тредов позволит намного упростить разворачивание-сворачивание мониторинга на произвольно взятой машине.
Если ваш JSON API не сильно тормозит, можно завести себе какое-нибудь простенькое хранилище сессионных данных (memcached или вообще FileSystemStorage, встроенный аж в werkzeug) и кэшировать ответ API туда, а при протухании кэша прямо во время очередного запроса просто дергать API и обновлять данные в хранилище.
А еще проще будет сделать банальный авторефреш страницы, и никаких искусственно созданных проблем с деплоем и тредами не будет. Если больше никакого функционала кроме показа БСКП не предвидится, это вообще делается на голом HTML+JS безо всяких бэкендов, тредов, серверов очередей, асинхронности и прочих трендовых штучек, которые абсолютно не нужны в "простом" наколенном мониторинге. А если нужен нормальный мониторинг - поставьте Zabbix :)
За идеи спасибо, сделать всё на HTML и JS — решение, близкое к идеальному, но всё же академический интерес к питону актуален, интересны его возможности.