Metadata-Version: 1.1
Name: pandaemonium
Version: 0.5.0
Summary: Framework for writing daemons, with API similar to threading and multiprocessing.
Home-page: UNKNOWN
Author: Ethan Furman
Author-email: ethan@stoneleaf.us
License: BSD License
Description: pandaemonium
        ============
        
        n. the abode of all the daemons [1]_
        
        pandaemonium provides a framework for writing daemons in Python.  The API is
        based on the threading/multiprocessing model [2]_ [3]_, so the primary way
        of creating your own daemon is to either subclass and override the ``run``
        method, or provide a function as the ``target`` to the ``Daemon`` class.
        
        Besides ``Daemon`` there is also a locking pid file -- ``PidLockFile``.
        ``PidLockFile`` can either be used manually, or, if a complete path and file
        name are provided to ``Daemon``, used automatically.
        
        
        simple usage
        ------------
        
            from pandaemonium import Daemon
        
            def DoSomethingInteresting():
                "Just like it says ;)"
                pass
        
            daemon = Daemon(target=DoSomethingInteresting)
            daemon.start()
            #
            # daemon.output will contain any stdout output generated during the
            # daemonizing process, up to the stdin/stdout/stderr redirection
            #
            # daemon.error contains anything sent to the daemon's stderr -- which
            # most likely means the daemon died due to an exception
            #
            # both can be parsed, examined, ignored, etc.
            
        
        or:
        
            from pandaemonium import Daemon
        
            class MyDaemon(Daemon):
                def run():
                    # do some interesting stuff
        
            md = MyDaemon().start()
        
        The sequence of events that takes place when `start()` is called (adapted from
        The Linux Programming Interface by Michael Kerrisk) is:
        
          - detach from the current process, creating a new session
          - turn off core dumps
          - set uid and gid
          - set umask
          - set working directory
          - create pid file
          - set signal handlers
          - close inherited file handles
          - redirect stdin/stdout/stderr
        
        If any exceptions occur or if any feedback is generated during the `start`
        process it will be available as the `error` and `output` attributes of the
        daemon instance, where the parent process can analyze, print, etc before
        quiting.
        
        Note:  In order to examine the `error` attribute you will need to catch the
        `DaemonError` exception that is raised.
        
        
        advanced usage
        --------------
        
        If more control is needed than what is provided by the parameters of Daemon
        then one has a couple options available:
        
          - if certain set up / initialization steps need to happen somewhere in the
            `start()` sequence, such as after setting the umask and before changing
            the working directory::
        
                Daemon.stage4()
                # stages 1-4 have now been completed
                # do custom steps here
                Daemon.start()
                # stages 5-9 have now been completed, and run() called
        
          - one can also override any of the stages in a subclass (make sure and
            decorate with `check_stage`:
        
                class MyDaemon(Daemon):
                    def run(self, ip):
                        # do stuff
                    @check_stage
                    def stage7(self):
                        # do some custom stuff with signals set up
        
                md = MyDaemon('192.168.11.1')
                md.start()
        
          - or, to simplify between foreground and daemon operation:
        
                foreground = sys.argv[2:3] == ['--foreground']
                pid_file = PidLockFile('/some/path/to/lock.pid')
                pid_file.acquire()
                if foreground:
                    pid_file.seal()
                else:
                    daemon = Daemon()
                    daemon.pid_file = pid_file
                    daemon.activate()
                # at this point, in either foreground or daemon mode, the pid file has
                # been sealed (has our correct pid written to it, and it has been
                # closed)
                run_main_program()
        
        If one's desire is to start the daemon and automatically have any output
        printed to screen, one can use `daemon.report()` which prints whatever was
        received from the daemon and then quits.
        
        
        Daemon
        ------
        
        ``Daemon(target=None, args=None, kwargs=None, working_directory='/', umask=0,
                 prevent_core=True, process_ids=None, inherit_files=None,
                 signal_map=None, stdin=None, stdout=None, stderr=None)``
        
            target
                function to call when daemonized
        
            args
                positional args to provide to target
        
            kwargs
                keyword args to provide to target
        
            detach
                `None` (default) means figure it out, `True` means yes, `False` means no.
                Figuring it out means if the parent process is `init`, or a `super
                server`, do not detach
        
            working_directory
                directory to change to (relative to chroot, if one is in effect)
        
            umask
                mask to use when creating files
        
            prevent_core
                prevent core dump files from being created
        
            process_ids
                tuple of (uid, gid) to switch process to (use (None, None) to disable)
        
            pid_file
                `None` (default), or
                a PidLockFile instance, or
                the string of where to create a PidLockFile
        
            inherit_files
                list of open files or file descriptors to keep open
        
            signal_map
                dictionary of signal names or numbers to method names or functions
        
            stdin / stdout / stderr
                streams to map the standard streams to
                default is `None` which is mapped to ``os.devnull``
        
        
        ``Daemon.run()``
        ''''''''''''''''
            Method representing the daemon's activity.
        
            You may override this method in a subclass.  The standard ``run``
            method invokes the callable object passed to the object's constructor as
            the `target` argument, if any, with sequential and keyword arguments taken
            from the `args` and `kwargs` arguments, respectively.
        
        ``Daemon.start()``
        ''''''''''''''''''
            Start the daemon's activity.
        
            This may be called at most once per daemon object.  It arranges for the
            object's ``run`` method to be invoked as a daemon process.
        
        ``Daemon.monitor()``
        ''''''''''''''''''''
            Collects stdout and stderr from Daemon process until stage 9 and attaches
            it to the daemon instance as ``output`` and ``error``.  Can be overridden
            if one wants to do more interesting stuff with the daemon's output
        
        ``Daemon.stage[1-9]()``
        ''''''''''''''''''''''''''
            One can override the various stages for even more customizations options.
            Make sure and decorate such functions with ``check_stage``.
        
        
        PidLockFile
        -----------
        
        ``PidLockFile(file_name, time_out)``
        
            file_name
                full path and name of file to use for locking
        
            time_out
                how long to wait before concluding that an existing held lock is not
                going to be released (default: -1, meaning conclude immediately)
        
        ``PidLockFile.acquire(time_out=None)``
        ''''''''''''''''''''''''''''''''''''''
            attempt to capture the lock file; if time_out is `None` use the time out
            specified when PidLockFile was created.
        
        ``PidLockFile.seal()``
        ''''''''''''''''''''''
            write the current process' PID into the acquired file and close it --
            should only be called by the daemon process or the stored PID will not be
            correct.
        
        ``PidLockFile.release()``
        '''''''''''''''''''''''''
            remove the lock file, releasing the lock.
        
        
        
        [1] http://dictionary.reference.com/browse/pandemonium
        [2] https://docs.python.org/2/library/threading.html#threading.Thread
        [3] https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development
Provides: pandaemonium
