Подтвердить что ты не робот

Общение с работающим демоном 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 немного больше, чем я хочу откусить на этом этапе. Следующий концептуальный вызов, я полагаю, заключается в том, как поговорить с моими рабочими потоками, не повесив их.

Еще раз спасибо.

4b9b3361

Ответ 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.