Yesterday, I've come up with the idea of using python context manager to ensure cleanup
available here. This time I am using that context manager to make a decorator.
Yesterday, I've come up with the idea of using python context manager to ensure cleanup
available here. This time I am using that context manager to make a decorator.
Raspberry Pi Safe Clean Up - the decorator way
Yesterday, I've come up with the idea of using python context manager to ensure cleanup
available here. This time I am using that context manager to make a decorator.
The context manager
# SafeGPIO.py
# updated, warning silenced
from RPi import GPIO
from exceptions import RuntimeWarning
import warnings
class SafeGPIO(object):
def __enter__(self):
return GPIO
def __exit__(self, *args, **kwargs):
with warnings.catch_warnings():
warnings.simplefilter("error") #turn warning into exceptions
try:
GPIO.cleanup()
except RuntimeWarning:
pass # silence it
The decorator
#decorators.py
from . import SafeGPIO
from RPi import GPIO
from functools import wraps
def safe_gpio(func):
"""
This decorator ensure GPIO.cleanup() is called when function call ends,
also it injects GPIO as first argument into your function
"""
@wraps(func) # using wraps preservses doc string
def wrapper(*args, **kwargs):
with SafeGPIO() as GPIO:
return func(GPIO, *args, **kwargs)
return wrapper
def gpio(func):
"""
This decorator injects GPIO as first argument into your function
"""
@wraps(func)
def wrapper(*args, **kwargs):
return func(GPIO, *args, **kwargs)
return wrapper
Use like this:
# decorator_test.py
from SafeGPIO.decorators import safe_gpio, gpio
from time import sleep
from random import choice, randint
GPIO_PINS = (3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26)
VALUES = (True, False)
@safe_gpio
def do_random_things_with_pins_for_ten_times(GPIO):
GPIO.setmode(GPIO.BOARD)
for pin in GPIO_PINS:
GPIO.setup(pin, GPIO.OUT)
for _ in xrange(10):
pin = choice(GPIO_PINS) # choose one of the GPIO pin
value = choice(VALUES) # output either true or false
sleep_seconds = randint(1,3) # sleep from 1 to 3 seconds
print "slected pin %d, output %r, sleep for %d seconds" %
(pin, value, sleep_seconds)
GPIO.output(pin, value)
sleep(sleep_seconds)
@safe_gpio
def do_real_work(GPIO):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
print "doing real work for 5 seconds"
GPIO.output(7, True)
sleep(5)
@safe_gpio # guarantee to clean up on exit
def main(GPIO):
do_random_things_with_pins_for_ten_times()
do_real_work()
if __name__ == '__main__':
main()