Python Advanced
Python Multithreading
Multithreading lets your Python program run multiple tasks that appear to happen at once, which is especially useful for tasks that spend time waiting, like network requests.
The threading Module
Python's built-in threading module lets you create and manage threads, which are lightweight units of execution that share the same memory space within a single program.
import threading
import time
def download(name):
print(f"Starting {name}")
time.sleep(2)
print(f"Finished {name}")
t1 = threading.Thread(target=download, args=("file1",))
t2 = threading.Thread(target=download, args=("file2",))
t1.start()
t2.start()
t1.join()
t2.join()
print("All downloads complete")The Global Interpreter Lock (GIL)
CPython (the standard Python interpreter) has a Global Interpreter Lock, or GIL, which allows only one thread to execute Python bytecode at a time. This means threads don't give you true parallel CPU computation for pure Python code.
Because of the GIL, multithreading does not speed up CPU-heavy work like number crunching — for that, use multiprocessing instead.
Why Threads Still Help for I/O-Bound Tasks
The GIL is released while a thread waits on I/O operations, such as reading a file, calling a web API, or querying a database. So even with the GIL, threads make I/O-bound programs much faster by overlapping their waiting time.
import threading
import time
def fetch(url):
print(f"Fetching {url}")
time.sleep(1) # simulates waiting for a network response
print(f"Done: {url}")
urls = ["site1.com", "site2.com", "site3.com"]
threads = [threading.Thread(target=fetch, args=(u,)) for u in urls]
for t in threads:
t.start()
for t in threads:
t.join()Thread and join()
You create a Thread object with a target function, start it with .start(), and use .join() to make the main program wait until that thread finishes before continuing.
| Method | Purpose |
|---|---|
| Thread(target=fn, args=(...)) | Creates a new thread to run fn |
| .start() | Begins running the thread |
| .join() | Waits for the thread to finish before continuing |
| .is_alive() | Checks whether the thread is still running |
Use multithreading for tasks like downloading files, calling APIs, or reading many files — anything that spends most of its time waiting, not computing.
