Всем привет.
Есть некий демон (служба? Как эта штука правильно называется) на питоне. Запускается через systemd. По некоему внутреннему триггеру непосредственно в скрипте нужно погасить демона, выполнить ряд команд, и запустить демона.
Для упрощения предметной области - это телеграмный бот с самоапдейтом из гита по команде пользователя.
Пробовал следующие реализации:
1) Из скрипта бота через subprocess.Popen (тут были разные варианты, не только Popen) запускается другой скрипт, который по идее должен не зависеть от текущего, и должен выполнить все нужные операции. Итог - основной демон стопится, но дальше ничего не происходит. Увы, логи тогда еще не снимались.
2) Из скрипта бота стартует (рестартует) другой демон, который уже и пытается выполнить нужные команды. Он стартует - это точно. Но логи пустые.
Собственно вопрос - как такую задачу в принципе правильнее решать?
GavriKos, Многопоточность выручает, если нужно несколько процессов одновременно
import threading
def proc_video():
# код реализующий процесс записи видео
pass
def proc_audio():
# код реализующий процесс записи аудио
pass
thread_video = threading.Thread(target=proc_video, name="proc_video")
thread_audio = threading.Thread(target=proc_audio, name="proc_audio")
thread_video.start()
thread_audio.start()
thread_video.join()
thread_audio.join()
Дополнительно
Нужно помнить про GIL, и если такой подход не подойдет можно воспользоваться модулем multiprocessing, а не threading, там параллельность достигается за счет процессов, и нет ни какого GIL и интерфейс у него такой же как и у threading (то есть можно просто импортировать multiprocessing, а не threading и работать с ним также).
Issue, вы говорите какими то отрывками, которые сложно связать воедино.
git pull то понятно.
Но кто его запустит, и кто рестартанет основной демон, и почему?
GavriKos, Я так понимаю, что когда вы открываете функцию, то основная программа виснет? Это из-за того, что вы запускаете все в одном потоке.
os.system(' ') - в кавычках можно прописать скрипт BASH/SHELL который будет обновляться
python -m - может использовать виртуальную среду venv если такая имеется и запускать в ней все что после -m...
А вообще в вашем случае, если не хочется разделять код на кучу файлов, то лучше использовать потоки. если в первую функцию ввести одну программу, а в другую функцию - другую программу, то они будут выполняться по очереди очень быстро. И не будет бот зависать, пока обновлением занимается.
В двух функциях audio и video можно указать бота и обновление. Тогда при запуске этого кода - у вас откроется и то, и другое.
Issue, потому что дальше идет апдейт из гита. Соответственно так или иначе - рестарт надо делать.
Конечно можно разделить на "ядро" и "модули" - но пока не дорос в питоне до такого.
#!/usr/bin/env python
# Собственно сам демон который будет решать вопросы
# Импортируем потоки
import threading
# Обьявим функции и в них запустим бота и обновление
def bot():
print('BOT')
def updater():
print('UPDATER')
from os import system as go
go('gksudo apt update bot') # или любая другая команда bash (если обнова через терминал ставится)
# Объявим потоки и назовем их
thread_Bot = threading.Thread(target=bot, name="BOT")
thread_Updater = threading.Thread(target=updater, name="UPDATER")
update = 1 # Получим инфо об обновлении
# Условие желательно поместить в цикл, что бы проверяло и обновляло не только во время запуска демона
if update == 1: # Если обновление есть то
thread_Updater.start() # Запустим обнову
else: # Иначе
thread_Bot.start() # Запустим бота
Можно еще функции в класс засунуть для порядка
class Bot():
def start():
print('start')
def stop():
print('stop')
Dr. Bacon, разделено. Работает. Больше был вопрос коммуникации между ними, но лок-файл - сработал. Подумываю с лок-файла переписать на что то вроде сокетов.
Issue, Эмм. я вот в код смотрю, да. Но хоть убейте - если это все условно одно приложение (не один py-файл - но один инстанс) - разве оно подтянет в ратнайме без перезапуска изменения? Насколько я понимаю если в процессе апдейта прилетит изменение сейчас используемого модуля - то фиг он там обновится без перезапуска того, кто его использует.