[Python] Deep Dive Into Thread

[Python] Deep Dive Into Thread

What Is a Thread?

A thread is a way to run multiple tasks concurrently in the same program.

Real-life example:

Let’s say you are going camping with friends, and you are the driver. In this example, we need to look at three key things:

  1. Project - What is our goal?

    • Our goal is to get to the destination safely.
  2. Process - How are we going to safely arrive at the destination?

    • It depends on the driver
  3. Thread - What are the requirements?

    • The driver should be able to look at the navigation and drive the car.

Therefore, there could be three ways to get to the destination.

  1. I (main thread) finds the route by myself, but I can’t do driving and looking at the map at the same time, which means I need to stop and look at the map. This results in longer time to arrive.

  2. I (process 1) can ask a friend (process 2) for a route that does not go on a trip together. However, this way seems like unproductive.

  3. I (main thread) have a navigation (sub thread) that shares data and memory with me. This way is the most EFFICIENT ← using multi thread.


Creating a Thread

Basic format:

# Thread library
import threading

def thread_func():
    # your code

# Create a thread
x = threading.Thread(target=thread_func, args=())

# Start a thread
x.start()

Let’s create one:

import logging
import threading
import time

# Thread function
def thread_func(name):
    logging.info("Sub-Thread %s: starting", name)
    time.sleep(3)
    logging.info("Sub-Thread %s: finishing", name)

# main
if __name__ == "__main__":
    format = "%(asctime)s: %(message)s"
    logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
    logging.info("Main-Thread: before creating thread")

    x = threading.Thread(target=thread_func, args=('First',))
    logging.info("Main-Thread: before running thread")

    x.start()

    logging.info("Main-Thread: wating for the thread to finish")
    logging.info("Main-Thread: All done!")

Output:

10:26:33: Main-Thread: before creating thread
10:26:33: Main-Thread: before running thread
10:26:33: Sub-Thread First: starting
10:26:33: Main-Thread: wating for the thread to finish
10:26:33: Main-Thread: All done!
10:26:36: Sub-Thread First: finishing

You may wonder why sub-thread finishes after the main thread finishes. If you want your main thread to wait for the sub-thread to end, you can use join().

x.start()
x.join()

Output:

10:26:59: Main-Thread: before creating thread
10:26:59: Main-Thread: before running thread
10:26:59: Sub-Thread First: starting
10:27:02: Sub-Thread First: finishing
10:27:02: Main-Thread: wating for the thread to finish
10:27:02: Main-Thread: All done!

Daemon Thread

Like a daemon, a daemon thread does not perform important tasks (low priorty). It runs in a background, doing some small works, such as garbage collecting and auto saving. These tasks are not something we can see.

Characteristics of daemon thread:

  • Background execution.

  • Automatically terminated when the main thread finishes even if they haven’t completed tasks.

Using Daemon Thread

x = threading.Thread(target=thread_func, args=('First', range(20000)), daemon=True)

It’s not a big deal. We can set daemon=True to make it a daemon thread.

Did you find this article valuable?

Support Jay's Dev Blog by becoming a sponsor. Any amount is appreciated!