Daemonizing python BaseHTTPServer

Я работаю над демоном, где мне нужно встроить HTTP-сервер. Я пытаюсь сделать это с помощью BaseHTTPServer, который, когда я запускаю его на переднем плане, работает отлично, но когда я пытаюсь развернуть демона в фоновом режиме, он перестает работать. Мое основное приложение продолжает работать, но BaseHTTPServer этого не делает.

Я считаю, что это связано с тем, что BaseHTTPServer отправляет данные журнала в STDOUT и STDERR. Я перенаправляю их в файлы. Вот фрагмент кода:

# Start the HTTP Server server = HTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']),HTTPHandler) # Fork our process to detach if not told to stay in foreground if options.foreground is False: try: pid = os.fork() if pid > 0: logging.info('Parent process ending.') sys.exit(0) except OSError, e: sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # Second fork to put into daemon mode try: pid = os.fork() if pid > 0: # exit from second parent, print eventual PID before print 'Daemon has started - PID # %d.' % pid logging.info('Child forked as PID # %d' % pid) sys.exit(0) except OSError, e: sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) logging.debug('After child fork') # Detach from parent environment os.chdir('/') os.setsid() os.umask(0) # Close stdin sys.stdin.close() # Redirect stdout, stderr sys.stdout = open('http_access.log', 'w') sys.stderr = open('http_errors.log', 'w') # Main Thread Object for Stats threads = [] logging.debug('Kicking off threads') while ... lots of code here ... server.serve_forever() 

Я делаю что-то не так здесь, или BaseHTTPServer каким-то образом помешал демонанизму?

Изменить: обновленный код, чтобы продемонстрировать дополнительный, ранее отсутствующий поток кода, и что log.debug отображается в моем раздвоенном фоновом демона. Я нахожу код после fork.

  • функция python, но не возвращающая значение. Должно быть просто
  • PyCharm. / usr / bin / python ^ M: плохой интерпретатор
  • Предоставьте подсказку навалом upserts
  • Как определить, повторяется ли строка в Python?
  • Доступ к mysql XAMPP через Python
  • Что делать, если __name__ == "__main__": делать?
  • эффективный массив python для преобразования массива numpy
  • Python Panda multi Line graph с использованием метки времени
  • 6 Solutions collect form web for “Daemonizing python BaseHTTPServer”

    После немного googling я, наконец, наткнулся на эту документацию BaseHTTPServer, после чего у меня получилось :

     from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SocketServer import ThreadingMixIn class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread.""" server = ThreadedHTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']), HTTPHandler) server.serve_forever() 

    Который по большей части приходит после того, как я развил и решил решить мою проблему.

    Вот как это сделать с библиотекой python-daemon :

     from BaseHTTPServer import (HTTPServer, BaseHTTPRequestHandler) import contextlib import daemon from my_app_config import config # Make the HTTP Server instance. server = HTTPServer( (config['HTTPServer']['listen'], config['HTTPServer']['port']), BaseHTTPRequestHandler) # Make the context manager for becoming a daemon process. daemon_context = daemon.DaemonContext() daemon_context.files_preserve = [server.fileno()] # Become a daemon process. with daemon_context: server.serve_forever() 

    Как обычно для демона, вам нужно решить, как вы будете взаимодействовать с программой после того, как она станет демоном. Например, вы можете зарегистрировать службу systemd или написать файл PID и т. Д. Однако все это выходит за рамки вопроса.

    Вы начинаете с создания экземпляра HTTPServer. Но вы на самом деле не говорите ему, чтобы он начал выступать в любом из поставляемого кода. В своем дочернем процессе попробуйте вызвать server.serve_forever() .

    См. Это для справки

    Простым решением для меня было переопределить метод log_message() , поэтому мы предотвращаем любые записи в stdout и избегаем проблем при демонировании.

     class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def log_message(self, format, *args): pass ... rest of custom class code ... 

    Просто используйте daemontools или какой-либо другой подобный скрипт вместо того, чтобы опрокинуть ваш собственный процесс демонализации. Гораздо лучше не использовать этот сценарий.

    Кроме того, ваш лучший вариант: не используйте BaseHTTPServer. Это действительно плохо. Существует много хороших HTTP-серверов для python, то есть вишня или паста . Оба включают готовые к использованию демонизирующие скрипты.

    Поскольку это требует ответов с тех пор, как я изначально был отправлен, я подумал, что поделился бы небольшой информацией.

    Проблема с выходом связана с тем, что обработчик по умолчанию для модуля протоколирования использует StreamHandler. Лучший способ справиться с этим – создать свои собственные обработчики. В случае, если вы хотите использовать модуль регистрации по умолчанию, вы можете сделать что-то вроде этого:

     # Get the default logger default_logger = logging.getLogger('') # Add the handler default_logger.addHandler(myotherhandler) # Remove the default stream handler for handler in default_logger.handlers: if isinstance(handler, logging.StreamHandler): default_logger.removeHandler(handler) 

    Также на этом этапе я перешел к использованию очень приятного проекта Tornado для встроенных HTTP-серверов.

    Python - лучший язык программирования в мире.