Хотя я считаю, что вам лучше использовать решение типа сервер-клиент, который прослушивает порт, то, что вы запрашиваете, возможно на 100% с использованием signal
и os
библиотек. Этот подход не будет хорошо работать с многопоточными программами, так как сигналы обрабатываются только родительским потоком в python. Кроме того, окна не реализуют сигналы таким же образом, поэтому параметры более ограничены.
Сигналы
Процесс "клиент" может отправлять произвольные сигналы, используя os.kill(pid, signal)
. Вам нужно будет просмотреть доступные сигналы и определить, какой из них вы хотите использовать (signal.NSIG
может быть хорошим вариантом, поскольку он не должен давить на любое другое поведение по умолчанию).
Процесс "демон" при запуске должен зарегистрировать обработчик для того, что делать, когда он получает выбранный вами сигнал. Обработчик - это функция, которую вы должны определить, которая получает сам полученный сигнал, а также текущий выполняемый кадр стека (def handler(signum, frame):
). Если вы делаете только одну вещь с этим обработчиком, и ему не нужно знать, что происходило, когда он вызывался, вы, вероятно, можете игнорировать оба эти параметра. Затем вы должны зарегистрировать обработчик с помощью signal.signal
ex: signal.signal(signal.NSIG, handler)
.
Оттуда вы захотите найти подходящий способ ожидания следующего сигнала, не затрачивая слишком много ресурсов. Это может быть так же просто, как зацикливание на os.sleep
команда, или вы могли бы попытаться получить фантазию. Я не уверен на 100%, как возобновится выполнение при возврате из обработчика сигнала, поэтому вам, возможно, придется позаботиться о глубине рекурсии (т.е. убедитесь, что вы не повторяете каждый раз, когда обрабатывается сигнал, или вы только когда-либо будете возможность обрабатывать ограниченное количество сигналов перед повторным запуском).
Сервер
Наличие процесса прослушивания порта (обычно называемого сервером, но функционально аналогичного описанию вашего «демона») вместо прослушивания сигналов операционной системы имеет несколько основных преимуществ.
- Порты могут отправлять данные, когда сигналы могут вызывать только события
- Порты больше похожи на кроссплатформенные
- Порты играют хорошо [r] с многопоточностью
- Порты позволяют легко отправлять сообщения по сети (например, создавать напоминания с телефона и выполнять на ПК)
Ожидание нескольких вещей одновременно
Чтобы решить необходимость ожидания нескольких процессов одновременно (прослушивание ввода, а также ожидание доставки следующего уведомления), у вас есть довольно много вариантов:
Сигналы на самом деле могут быть хорошим вариантом использования, поскольку signal.SIGALRM
можно использовать как удобно переустанавливаемый будильник (если вы используете UNIX). Вы должны настроить обработчик так же, как и раньше, и просто установить будильник для следующего уведомления. После установки будильника вы можете просто возобновить прослушивание порта для новых задач. Если приходит новое задание, повторная установка будильника переопределит существующее, поэтому обработчику потребуется извлечь следующее уведомление в очереди и заново установить будильник, как только будет выполнено первое задание.
Потоки могут быть использованы для опроса очереди задач уведомлений, или может быть создан отдельный поток для ожидания каждой задачи. Это не особенно элегантное решение, однако оно будет эффективным и простым в реализации.
Наиболее элегантное решение, вероятно, заключалось бы в использовании asyncio
сопрограмм, однако я не так хорошо разбираюсь в asyncio и признаю, что они немного более запутанны, чем потоки.