Multithreaded Python Tutorial with the “Threadworms” Demo

The code for this tutorial can be downloaded here: threadworms.py or from GitHub. This code works with Python 3 or Python 2, and you need Pygame installed as well in order to run it.

threads and multithreaded programs in Python, aimed at beginning programmers. It helps if you know the basics of classes (what they are, how you define methods, and that methods always have self as the first parameter, what subclasses (i.e. child classes) are and how a method can be inherited from a parent class, etc.) Here’s a more in-depth classes tutorial.

The example used is a “Nibbles” or “Snake” style clone that has multiple worms running around a grid-like field, with each worm running in a separate thread.

What are threads and why are they useful?

You can skip this section if you already know what threads are and just want to see how to use them in Python.

When you run a normal Python program, the program execution starts at the first line and goes down line by line. Loops and function calls may cause the program execution to jump around, but it is fairly easy to see from the code which line will get executed next at any given point. You can put your finger on the first line of code in the .py file on the screen, and then trace through the next lines of code that are executed. This is single-threaded programming.

However, using multiple threads is like putting a second finger down on your code. Each finger still moves the same way, but now they are executing code simultaneously.

Actually, they aren’t executing simultaneously. Your two fingers are taking turns at which one executes code. Computers with multicore CPUs can actually run multiple instructions simultaneously, but there is a feature of Python programs called the GIL (Global Interpreter Lock) that limits a Python program to one core only.

The Python interpreter will run one thread for a while, and then pause it to run another thread for a while. But it does this so fast that it seems like they are running simultaneously.

You can start dozens or hundreds of threads in your program (that’s a lot of fingers). This doesn’t automatically make your programs dozens or hundreds of times faster though (all the threads are still sharing the same CPU) but it can make your program more efficient.

For example, say you write a function that will download a file full of names, then sorts the names, and then writes these names to a file on your computer. If there are hundreds of files your program needs to process, you would put a call to this function in a loop and it would handle each file serially: download, sort, write, download, sort, write, download, sort, write…

Each of these three steps use different resources on your computer: downloading uses the network connection, sorting uses the CPU, writing the file uses the hard drive. Also, there are tiny pauses within each of these steps. For example, the server you are downloading the file from may be slow and your computer’s Internet connection has bandwidth to spare.

It would be better if you could call this function hundreds of times in parallel by using one thread for each file. Not only would this make better use of your bandwidth, but if some files download sooner than others, the CPU can be used to sort them while the network connection continues to work. This makes more efficient use of your computer.

What makes multithreaded programming tricky?

Of course, in the above case, each thread is doing its own separate thing and doesn’t need to communicate or synchronize anything with the other threads. You could just write the simple single-threaded version of the download-sort-write program and run the program hundreds of times separately. (Though it might be a pain to type & click each time to run the program each with a different file to download.)

Many multithreaded programs share access to the same variables, but this is where things can get tricky.

Page 1 of 10 | Next page