Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

Yesterday, I've come up with the idea of using python context manager to ensure cleanup available here 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.

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.

Source Link

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()
lang-py

AltStyle によって変換されたページ (->オリジナル) /