Short guide on creating threads in Python

Mustafa Aslanov
4 min readDec 14, 2020

Coming from the latest assignment on Advanced Software Paradigms, after a bit of research I found out that one can create threads in various ways in Python. One can call those methods as *manual old style* and *new optimal style*.

What is a thread?

A thread is an independent set of values for the processor registers (for a single core). Since this includes the Instruction Pointer (aka Program Counter), it controls what executes in what order. It also includes the Stack Pointer, which had better point to a unique area of memory for each thread or else they will interfere with each other.

Threads are the software unit affected by control flow (function call, loop, goto), because those instructions operate on the Instruction Pointer, and that belongs to a particular thread. Threads are often scheduled according to some prioritization scheme (although it’s possible to design a system with one thread per processor core, in which case every thread is always running and no scheduling is needed).

In fact the value of the Instruction Pointer and the instruction stored at that location is sufficient to determine a new value for the Instruction Pointer. For most instructions, this simply advances the IP by the size of the instruction, but control flow instructions change the IP in other, predictable ways. The sequence of values the IP takes on forms a path of execution weaving through the program code, giving rise to the name “thread”.

There are single-threaded and multi-threaded programs one can create using different programming languages.

Single-threaded programming.

In computer programming, single-threading is the processing of one command at a time. In the formal analysis of the variables’ semantics and process state, the term single threading can be used differently to mean “backtracking within a single thread”, which is common in the functional programming community.

Creating a single thread in Python is fairly simple. First, you need to import the library “threading”.

Simple block of code below will start a single thread for you:

thread = threading.Thread(target =(do_something), args=())thread.start()

Here, you assign the created thread to a target, which a function in your code. args is an optional argument, depending if your function requires any arguments to pass in. If there are none, then you can ignore it. In the end, you can just simlpy .start() the thread and it will run. Simple as that! You may also add time.sleep() function in your do_something() function which will send to sleep your thread depending on time you provided.

Multi-threaded programming.

Multithreading is mainly found in multitasking operating systems. Multithreading is a widespread programming and execution model that allows multiple threads to exist within the context of one process. These threads share the process’s resources, but are able to execute independently. The threaded programming model provides developers with a useful abstraction of concurrent execution. Multithreading can also be applied to one process to enable parallel execution on a multiprocessing system.

Multithreading libraries tend to provide a function call to create a new thread, which takes a function as a parameter. A concurrent thread is then created which starts running the passed function and ends when the function returns. The thread libraries also offer data synchronization functions.

In Python there are different ways to create multiple threads. The old and manual style was to create for loop and call threads one by one. See the example code:

threads = [threading.Thread(target =(do_something), args=()) for _ in range(limit)][t.start() for t in threads]
[t.join() for t in threads]

The first line just creates a list of threads with specified limit. Usually, it is just the CPU’s number of your system. The main difference with previous code of single-threading, is the

[t.join() for t in threads]

This ensures that all threads will run together and won’t wait until one finishes. Noteworthy moment is that you can’t start and join threads at the same time, it won’t work.

Another way of creating multi-threaded programming is using library “multiprocessing”. Structurally creating new threads is very similar to “threading” library methods.

threads = [multiprocessing.Process(target=[target],args=([args]) for _ in range(limit))[thread.start() for thread in threads][thread.join() for thread in threads]

This will create multiple multiprocessing threads within the specified limit.

And one another way, is the newly created library which one can use only with Python 3.2+ version. For that you will need another library called “concurrent.futures”.

with concurrent.futures.ProcessPoolExecutor() as executor:    [executor.submit([target], [optional arguments]) for _ in range(limit)]

This new way of creating threads saves some time for as it doesn’t require for the programmer to use .start() and .join() methods. They will start automatically. Using the keyword “with” will ensure that all threads will shutdown only after they all finished executing. If you don’t won’t that you can create simple for loop instead. Noteworthy to mention that there are two sub-libraries of concurrent.futures:

  • .ProcessPoolExecutor()
  • .ThreadPoolExecutor()

The main differences between are that:

ProcessPoolExecutor runs each of your workers in its own separate child process.

ThreadPoolExecutor runs each of your workers in separate threads within the main process.

This will conclude my short guide on how one can create single-threaded and multi-threaded programs in Python. Hope you enjoyed!

--

--