Python: Creating a singleton (to control an Arduino)

A while ago I was writing a tool in python to communicate with a sensor on an Arduino. The idea was to have a class for the Arduino that would hold the connection and handle the reading and writing to the serial port. However that way I needed to have the object maintain the connection and the open COM port (this was on windows), but this meant that I could not have multiple objects. Why? Because you can only have one connection to a COM port. The solution – use a Singleton design pattern.

What is a singleton?

Basically it is a class, that has only one object. No matter how many times you call the class you will get _the exact same_ object back. Not a copy, not one that looks like it, the exact same object. There is only one object for that class.

Creating a Singleton in Python

So how do we create a singleton in python? There are a couple of ways of doing this in python, but here’s what I did:

First let’s look at the simple Arduino class. We’ll just give it a single function ‘connect’ that sets the serial port.

Then when we create Arduino objects we will get, as expected, different objects:

Next let’s create a Singleton class:

To enable this decorator we uncomment the “#@Singleton” in the snippet above.

When the code is ran the python interpreter comes across the decorator and run’s the Singleton.__init__() method setting self.klass to the Arduino class.

When we create an Arduino object, the Singleton.__call__() function is called and this checks if self.instance is None, and it will be the first time, and then sets self.instance to self.klass (ie assigns it to an instance of Arduino)

Now if we try and create two different Arduino instances we find they are both the same:

The effect of this is that in our code we can create multiple Arduino instances if needed but they will in reality be the same instance that manages the serial connection.

Finally this does put extra responsibility on your code to manage what’s being sent and received down that serial line. If you have two threads running, potentially writing to the serial port at the same time you will get garbage. Some form of semaphore or mutex lock would be needed. But that’s a topic for another day.

Leave a Reply

Your email address will not be published. Required fields are marked *