The Midlife Geek

Ramblings of a middle aged engineer, runner and open source enthusiast

Tag: Computer Science

More on threads

Python

In an earlier post, I used Threads but the thread module in Python when I should be using threading. The documentation for threading says it builds upon the thread module (renamed _thread). The docs for _thread say:

This module provides low-level primitives for working with multiple threads (also called light-weight processes or tasks) — multiple threads of control sharing their global data space. For synchronization, simple locks (also called mutexes or binary semaphores) are provided. The threading module provides an easier to use and higher-level threading API built on top of this module.

docs.python.org

That makes sense, so I should be using the threading module. So why is there a leading underscore on thread? The Style Guide (PEP 8) says it’s a weak internal use indication and that for example modules with an underscore are not imported when using an asterisk.

There are two ways to use this module. Define a subclass and override the run method or to use the Thread class’s default run method. I’ll use the second method here.

The Python 2.x code I was using looked like this:

1
2
import thread
thread.start_new_thread(scroll, (text,))

The new code:

1
2
3
4
5
6
7
8
import threading

def scroll(text):
    print(text)

text = 'Example text'
thread = threading.Thread(target=scroll, args=(text,))
thread.start()

So this isn’t that different but it is a lot more readable. The arguments are explicit and there’s no ambiguity.

Fluent Python (Ramalho, 2015) suggests using   concurrent.futures package with Python 3.x. ThreadPoolExecutor and ProcessPoolExecutor implement interfaces to submit threads or processes respectively for execution. I’ll expand on this in a future post as it is useful to submit multiple tasks and collect results – however that’s not what is needed in this example.

Rainbow hat – decorators, arguments and threads

Raspberry Pi

Playing with Rainbow Hat I learned a few things about Python as a result I found out what a decorator is, the difference between args and kwargs and threads. I also learned that a lot of guides don’t understand either.

If you can’t explain it simply, you don’t understand it well enough.

Albert Einstein

Decorators

Rainbow Hat documentation says “use touch handlers either by passing in a function by name, or using the method as a decorator”.

Learning Python (Lutz, 2013) dedicates a chapter to decorators and sums it up rather well:

In short, decorators provide a way to insert automatically run code at the end of function and class definition statements—at the end of a def for function decorators, and at the end of a class for class decorators.

With similar notation to Java’s annotations:

1
@decorator_function def function(arguments): ...

Python is running one function through another and binding the result to the original function name.

1
2
3
4
def function(arguments):
    ...

function = decorator_function(function)

For example, Python has a built in function that returns a static method staticmethod(function). To make example_func static, we put:

1
2
3
@staticmethod
def example_func(arg)
    ...

Which is rebound to:

1
staticmethod(example_func)(arg)

So now I know what a decorator is in Python, I used it for the buttons. What to use them for though? I figure that they should control speed of LED, sequence or colour. That’s going to need a thread running as an event handler.

A short digression on arguments

What on earth is a key-worded argument? Lots of documentation refers to *args and **kwargs but had no idea what it was. Arguments passed to functions are read left to right:

function('Dougie', 42)

But we can also use a key-value pair:

function(name='Dougie', age=42)

Apart from improving readability in the function call, default arguments can be assigned in the function definition:

def function(name='Dougie', age=42)

By convention these are referred to as arg and kwarg. Almost there – that just leaves the *. Python lets you define functions that take any number of arguments, assembling them into a tuple. If you use key-value arguments, it assembles a dictionary.

def function(**kwargs): {...}

Now the clever(er) bit because if you do the same on the function call, Python unpacks the argument into individual arguments (*arg) or key-value pairs (**kwarg).

function(**kwargs)

Back to the main thread

The Rainbow Hat has buttons so I want to use these to control rainbow speed. This seems suited to a thread running an event handler. The syntax for the thread library (hopefully explaining the digression) is:

thread.start_new_thread (function_name, (*args, **kwargs))

Concurrency in Python is probably a post in its own right. The CPython interpreter bytecode isn’t fully thread safe. There are different interpretations of what that means so I’ll use the Open University definition:

A class is considered thread-safe if its instances behave under concurrent method calls as if they were called sequentially.

M362 Developing concurrent distributed systems (THE OU, 2008)

Python source code is compiled to bytecode which is run in a VM as machine code. In order to ensure only one thread executes bytecode at once the current thread has to hold a global lock (Global Interpreter Lock (GIL)).

This means multiple processor cores aren’t being used. In this application it doesn’t matter because the interpreter emulates concurrency by routinely switching threads.


Masters degree

With a bachelors completed, a sense of “what now” quickly settles in and a masters degree is a logical next step. After graduation, the Open University (OU) was quick to respond to tweets:

Masters degree

Continue reading

Euler 15 – How many routes through a 20×20 grid?

Struggled to get my head around Euler problem 15:

Starting at the top left of a 20×20 grid and only moving right and down, how many routes are there?

I figured that this was a combinatorics problem but couldn’t see what to count or choose from.

Continue reading

© 2019 The Midlife Geek

Theme by Anders NorenUp ↑