I have made a class to represent my led strip, and I would like to switch off the strip when I stop it (aka when the program stops and the object is destroyed). Hence, as I would do in C++, I created a destructor to do that. But it looks like Python call it after it destroyed the object. Then I got a segmentation fault error.
Here is my class, the destructor just have to call the function to set the colour of each LED to 0.
class LedStrip: def __init__(self, led_count, led_pin, led_freq_hz, led_dma, led_invert, led_brightness, led_channel, color = MyColor(0,0,0)): self.__strip = Adafruit_NeoPixel(led_count, led_pin, led_freq_hz, led_dma, led_invert, led_brightness, led_channel) self.__color = color self.__strip.begin() def __del__(self): self.__color = MyColor(0,0,0) self.colorWipe(10) # ATTRIBUTS (getter/setter) @property def color(self): return self.__color @color.setter def color(self, color): if isinstance(color, MyColor): self.__color = color else: self.__color = MyColor(0,0,0) def __len__(self): return self.__strip.numPixels() # METHODS def colorWipe(self, wait_ms=50): """Wipe color across display a pixel at a time.""" color = self.__color.toNum() for i in range(self.__strip.numPixels()): self.__strip.setPixelColor(i, color) self.__strip.show() time.sleep(wait_ms/1000.0)
MyColor
is just a class that I made to represent an RGB colour. What would be the correct what to achieve that task in Python? I come from C++, hence my OOP method is really C++ oriented, so I have some difficulties thinking in a pythonic way.
Thanks in advance
Advertisement
Answer
You have to be very careful when writing __del__
methods (finalizers). They can be called at virtually any time after an object is no longer referenced (it doesn’t necessarily happen immediately) and there’s really no guarantee that they’ll be called at interpreter exit time. If they do get called during interpreter exit, other objects (such as global variables and other modules) might already have been cleaned up, and therefore unavailable to your finalizer. They exist so that objects can clean up state (such as low-level file handles, connections, etc.), and don’t function like C++ destructors. In my Python experience, you rarely need to write your own __del__
methods.
There are other mechanisms you could use here. One choice would be try/finally
:
leds = LedStrip(...) try: # application logic to interact with the LEDs finally: leds.clear() # or whatever logic you need to clear the LEDs to zero
This is still pretty explicit. If you want something a bit more implicit, you could consider using the Python context manager structure instead. To use a context manager, you use the with
keyword:
with open("file.txt", "w") as outfile: outfile.write("Hello!n")
The with
statement calls the special __enter__
method to initialize the “context”. When the block ends, the __exit__
method will be called to end the “context”. For the case of a file, __exit__
would close the file. The key is that __exit__
will be called even if an exception occurs inside the block (kind of like finally
on a try
block).
You could implement __enter__
and __exit__
on your LED strip, then write:
with LedStrip(...) as leds: # do whatever you want with the leds
and when the block ends, the __exit__
method could reset the state of all the LEDs.