controlling some GPIOs

Ben Finney ben+python at benfinney.id.au
Tue Apr 7 20:53:25 UTC 2015


On 07-Apr-2015, Gilles Risch wrote:

> I'd like to use the python-daemon library on a raspberry pi to
> perform some IO tasks on the GPIOs.

Thanks for trying ‘python-daemon’.

> I must configure the pins and create some files during the start of
> the daemon.

I will assume this can be satisfied simply by putting such actions
inside the daemon (i.e., within the function that you run after
opening the DaemonContext). That is:

* Start the daemon (by opening the DaemonContext).

* Then configure the pins.

* Then create some files.

Such as::

    def do_main_program():
        configure_pins()
        create_some_files()
        do_other_stuff()

    daemon_context = daemon.DaemonContext()

    with daemon_context:
        do_main_program()

    program_cleanup()

> These files should be removed when I stop the daemon.

That sounds like a job for a context manager::

    def do_main_program():
        configure_pins()

        foo_file = open(FOO_FILE_PATH)
        with foo_file:
            do_other_stuff()

For stacking several files as the context, the ‘contextlib.ExitStack’
<URL:https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack>
class from the standard library can help::

    import contextlib

    startup_file_paths = [FOO_FILE_PATH, BAR_FILE_PATH]

    def do_main_program():
        configure_pins()

        with contextlib.ExitStack() as startup_file_stack:
            startup_files = [
                    startup_file_stack.enter_context(open(file_path))
                    for file_path in startup_file_paths]
            do_other_stuff()

If you need to do more complex stuff that should be cleaned up when
the context exits, put the behaviour in a context manager class.

    class GPIOContext(object):
        """ Context manager to set up and shut down the GPIO. """

        def __init__(self, foo, bar):
            """ Initialise the GPIO context. """
            # Whatever customisation for a specific GPIO context is needed,
            # if any, using `foo` and `bar` or whatever parameters.

        def __enter__(self):
            """ Enter the GPIO context. """
            configure_pins()
            self.startup_files = open_all_the_files()

            return self

        def __exit__(self, exc_type, exc_value, exc_traceback):
            """ Exit the GPIO context on receiving an exception, if any. """
            for gpio_file in self.startup_files:
                gpio_file.close()
            reset_pins()

            return False

    def do_main_program():
        with GPIOContext(foo, bar) as gpio_context:
            quux_file = gpio_context.startup_files['quux']
            do_main_program(quux_file)

See the documentation for context managers and the ‘with’ statement
<URL:https://docs.python.org/3/reference/datamodel.html#context-managers>.

> Is there a simple way do do that when I implement my daemon? Can I
> do that in __init__ and __del__ or is that a bad practice?

I think all of what you describe should be done without changing how
the daemon context operates. Do all of this after opening the daemon
context.

Instead, create another context, using existing context managers (such
as the files) or your own custom context manager (written as a
specific class).

-- 
 \              “When cryptography is outlawed, bayl bhgynjf jvyy unir |
  `\                                              cevinpl.” —Anonymous |
_o__)                                                                  |
Ben Finney <ben at benfinney.id.au>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.alioth.debian.org/pipermail/python-daemon-devel/attachments/20150408/2b59505e/attachment.sig>


More information about the python-daemon-devel mailing list