python-daemon

README.md

python-daemon Frequently Asked Questions

:Author: Ben Finney :Updated: 2010-04-10

.. contents:: .. 1 General 1.1 What is the purpose of the ‘python-daemon’ library? 1.2 How can I run a service communicating with a separate daemon process? 2 File descriptors 2.1 Why does the output stop after opening the daemon context? 2.2 How can I preserve a ‘logging’ handler's file descriptor?

General

What is the purpose of the ‘python-daemon’ library?

The ‘python-daemon’ library has a deliberately narrow focus: that of being a reference implementation for PEP 3143_, “Standard daemon process library”.

.. _PEP 3143: http://www.python.org/dev/peps/pep-3143

How can I run a service communicating with a separate daemon process?

As specified in PEP 3143_, the ‘python-daemon’ library is specifically focussed on the goal of having the current running program become a well-behaved Unix daemon process. This leaves open the question of how this program is started, or about multiple programs interacting. As detailed in PEP 3143:

A daemon is not a service

There is a related concept in many systems, called a “service”. A
service differs from the model in this PEP, in that rather than
having the *current* program continue to run as a daemon process,
a service starts an *additional* process to run in the background,
and the current process communicates with that additional process
via some defined channels.

The Unix-style daemon model in this PEP can be used, among other
things, to implement the background-process part of a service; but
this PEP does not address the other aspects of setting up and
managing a service.

A possible starting point for such a “service” model of execution is in a message from 2009-01-30_ to the python-ideas forum.

.. _message from 2009-01-30: http://mail.python.org/pipermail/python-ideas/2009-January/002606.html

File descriptors

Why does the output stop after opening the daemon context?

The specified behaviour in PEP 3143_ includes the requirement to detach the process from the controlling terminal (to allow the process to continue to run as a daemon), and to close all file descriptors not known to be safe once detached (to ansure any files that continue to be used are under the control of the daemon process).

If you want the process to generate output via the system streams ‘sys.stdout’ and ‘sys.stderr’, set the ‘DaemonContext’'s ‘stdout’ and/or ‘stderr’ options to a file-like object (e.g. the ‘stream’ attribute of a ‘logging.Handler’ instance). If these objects have file descriptors, they will be preserved when the daemon context opens.

How can I preserve a ‘logging’ handler's file descriptor?

The ‘DaemonContext.open’ method conforms to PEP 3143_ by closing all open file descriptors, but excluding those files specified in the ‘files_preserve’ option. This option is a list of files or file descriptors.

The Python standard library ‘logging’ module provides log handlers that write to streams, including to files via the ‘StreamHandler’ class and its sub-classes. The documentation (both the online logging module documentation_ and the docstrings for the code) makes no mention of a way to get at the stream associated with a handler object.

However, looking at the source code for ‘StreamHandler’, in Python 2.5 as /usr/lib/python2.5/logging/__init__.py, shows a ‘stream’ attribute that is bound to the stream object. The attribute is not marked private (i.e. it is not named with a leading underscore), so we can presume it is part of the public API.

That attribute can then be used to specify that a logging handler's file descriptor should, when the ‘DaemonContext’ opens, be excluded from closure::

import logging
import daemon

# any subclass of StreamHandler should provide the ‘stream’ attribute.
lh = logging.handlers.TimedRotatingFileHandler(
    "/var/log/foo.log",
    # …
    )

# … do some logging and other activity …

daemon_context = daemon.DaemonContext()
daemon_context.files_preserve = [lh.stream]

daemon_context.open()

# … continue as a daemon process …

.. _logging module documentation: http://docs.python.org/library/logging

.. Local variables: mode: rst coding: utf-8 time-stamp-format: "%:y-%02m-%02d" time-stamp-start: "^:Updated:[ ]+" time-stamp-end: "$" time-stamp-line-limit: 20 End: vim: filetype=rst fileencoding=utf-8 :