Общение с работающим демоном python
Я написал небольшое приложение Python, которое работает как демон. Он использует потоки и очереди.
Я ищу общие подходы к изменению этого приложения, чтобы я мог общаться с ним во время его работы. В основном я хотел бы следить за своим здоровьем.
Вкратце, я хотел бы сделать что-то вроде этого:
python application.py start # launches the daemon
Позже, я хотел бы быть в состоянии прийти и сделать что-то вроде:
python application.py check_queue_size # return info from the daemonized process
Чтобы быть ясным, у меня нет проблем с внедрением синтаксиса, вдохновленного Django. То, что я не знаю, как это сделать, - отправить сигналы на демонтированный процесс (начало) или как написать демона для обработки и реагирования на такие сигналы.
Как я уже говорил выше, я ищу общие подходы. Единственное, что я вижу сейчас, - это показать, что демон постоянно регистрирует все, что может потребоваться для файла, но я надеюсь, что там будет менее грязный способ сделать это.
ОБНОВЛЕНИЕ: Ничего себе, много отличных ответов. Спасибо. Я думаю, что посмотрю как на Pyro, так и на web.py/Werkzeug, потому что Twisted немного больше, чем я хочу откусить на этом этапе. Следующий концептуальный вызов, я полагаю, заключается в том, как поговорить с моими рабочими потоками, не повесив их.
Еще раз спасибо.
Ответы
Ответ 1
Как насчет того, чтобы запустить HTTP-сервер?
Кажется сумасшедшим, но работает простой веб-сервер для администрирования вашего
сервер требует всего несколько строк, используя web.py
Вы также можете рассмотреть возможность создания unix-канала.
Ответ 2
Еще один подход: используйте Pyro (объекты удаленного доступа Python).
Pyro в основном позволяет публиковать экземпляры объектов Python в качестве служб, которые можно назвать удаленно. Я использовал Pyro для конкретной цели, которую вы описали, и я нашел, что она работает очень хорошо.
По умолчанию демон Pyro-сервера принимает соединения со всех сторон. Чтобы ограничить это, используйте либо валидатор соединения (см. Документацию), либо поставьте host='127.0.0.1'
в конструктор Daemon
только для прослушивания локальных подключений.
Пример кода, взятого из документации Pyro:
Сервер
import Pyro.core
class JokeGen(Pyro.core.ObjBase):
def __init__(self):
Pyro.core.ObjBase.__init__(self)
def joke(self, name):
return "Sorry "+name+", I don't know any jokes."
Pyro.core.initServer()
daemon=Pyro.core.Daemon()
uri=daemon.connect(JokeGen(),"jokegen")
print "The daemon runs on port:",daemon.port
print "The object uri is:",uri
daemon.requestLoop()
Client
import Pyro.core
# you have to change the URI below to match your own host/port.
jokes = Pyro.core.getProxyForURI("PYROLOC://localhost:7766/jokegen")
print jokes.joke("Irmen")
Другим подобным проектом является RPyC. Я не пробовал RPyC.
Ответ 3
Используйте werkzeug и включите в свой демон HTTP-сервер WSGI.
В вашем демоне есть набор небольших приложений WSGI для ответа на информацию о состоянии.
Ваш клиент просто использует urllib2 для отправки POST или GET-запросов на localhost: somePort. Ваш клиент и сервер должны согласовать номер порта (и URL-адреса).
Это очень просто реализовать и очень масштабируемо. Добавление новых команд - тривиальное упражнение.
Обратите внимание, что вашему демону не нужно отвечать в HTML (что часто бывает просто). Наши демоны отвечают на WSGI-запросы с объектами статуса, закодированными JSON.
Ответ 4
Я бы использовал скрученный с именованным каналом или просто открыл сокет. Взгляните на эхо-сервер и клиент examples. Вам нужно будет изменить сервер эха, чтобы проверить, какая строка передана клиентом, а затем ответить любой запрошенной информацией.
Из-за проблем с потоками Python у вас возникнут проблемы с ответом на информационные запросы, одновременно продолжая делать все, что должен делать демон. Асинхронные методы или разветвление других процессов - ваш единственный реальный вариант.
Ответ 5
# your server
from twisted.web import xmlrpc, server
from twisted.internet import reactor
class MyServer(xmlrpc.XMLRPC):
def xmlrpc_monitor(self, params):
return server_related_info
if __name__ == '__main__':
r = MyServer()
reactor.listenTCP(8080, Server.Site(r))
reactor.run()
клиент может быть написан с помощью xmlrpclib, проверьте код примера здесь.
Ответ 6
Предполагая, что вы находитесь под * nix, вы можете отправлять сигналы в запущенную программу с kill
из оболочки (и аналоги во многих других средах). Чтобы обработать их изнутри python, проверьте модуль signal.
Ответ 7
Вы можете связать его с Pyro (http://pythonhosted.org/Pyro4/) удаленным объектом Python. Он позволяет удаленно обращаться к объектам python. Он легко реализуется, имеет низкие накладные расходы и не столь же инвазивный, как Twisted.