Creating Threads

Introduction

A thread is the smallest unit of execution within a process. Python allows developers to create multiple threads so that different tasks can run concurrently within the same program.

Creating threads is useful when working with:

  • File Operations

  • Network Requests

  • API Calls

  • Web Scraping

  • Selenium Automation

  • Background Tasks

  • Data Processing

Python provides the built-in threading module to create and manage threads.

In this tutorial, you will learn different ways to create threads, practical examples, automation testing use cases, common mistakes, and best practices.


Importing the Threading Module

Before creating threads, import the threading module.

import threading

Method 1: Creating a Thread Using a Function

This is the most common method.

Example

import threading

def display_message():
    print("Thread is running")

thread = threading.Thread(
    target=display_message
)

thread.start()

Output

Thread is running

Understanding the Code

thread = threading.Thread(
    target=display_message
)
Parameter Description
Thread() Creates a thread object
target Function executed by the thread

Start execution using:

thread.start()

Method 2: Creating a Thread with Arguments

Example

import threading

def greet(name):
    print(f"Hello {name}")

thread = threading.Thread(
    target=greet,
    args=("John",)
)

thread.start()

Output

Hello John

Passing Multiple Arguments

Example

import threading

def add(a, b):
    print(a + b)

thread = threading.Thread(
    target=add,
    args=(10, 20)
)

thread.start()

Output

30

Method 3: Creating Multiple Threads

Example

import threading

def worker(number):
    print(
        f"Thread {number} Running"
    )

for i in range(5):

    thread = threading.Thread(
        target=worker,
        args=(i,)
    )

    thread.start()

Output

Thread 0 Running
Thread 1 Running
Thread 2 Running
Thread 3 Running
Thread 4 Running

(Output order may vary.)


Waiting for Threads Using join()

Example

import threading
import time

def task():

    time.sleep(2)

    print("Task Completed")

thread = threading.Thread(
    target=task
)

thread.start()

thread.join()

print("Program Finished")

Output

Task Completed
Program Finished

Creating Multiple Threads and Waiting for Completion

Example

import threading

def worker(number):

    print(
        f"Thread {number} Running"
    )

threads = []

for i in range(5):

    thread = threading.Thread(
        target=worker,
        args=(i,)
    )

    threads.append(thread)

    thread.start()

for thread in threads:
    thread.join()

print("All Threads Completed")

Method 4: Creating Threads by Extending Thread Class

Python allows you to create custom thread classes.

Example

import threading

class MyThread(threading.Thread):

    def run(self):
        print("Custom Thread Running")

thread = MyThread()

thread.start()

Output

Custom Thread Running

Creating Multiple Custom Threads

Example

import threading

class WorkerThread(
    threading.Thread
):

    def __init__(self, number):

        super().__init__()

        self.number = number

    def run(self):

        print(
            f"Thread {self.number}"
        )

for i in range(3):

    thread = WorkerThread(i)

    thread.start()

Output

Thread 0
Thread 1
Thread 2

Naming Threads

Example

import threading

def worker():

    print(
        threading.current_thread().name
    )

thread = threading.Thread(
    target=worker,
    name="LoginThread"
)

thread.start()

Output

LoginThread

Checking if a Thread is Alive

Example

import threading
import time

def task():

    time.sleep(3)

thread = threading.Thread(
    target=task
)

thread.start()

print(thread.is_alive())

Output

True

Getting Current Thread Information

Example

import threading

def worker():

    print(
        threading.current_thread()
    )

thread = threading.Thread(
    target=worker
)

thread.start()

Sample Output

<Thread(Thread-1, started)>

Daemon Threads

Daemon threads run in the background.

Example

import threading
import time

def background_task():

    while True:

        print("Running")

        time.sleep(1)

thread = threading.Thread(
    target=background_task,
    daemon=True
)

thread.start()

print("Main Program Ends")

When the main program exits, daemon threads terminate automatically.


Real-World Example: Download Files Concurrently

Sequential Execution

import time

for i in range(3):

    print(
        f"Downloading File {i}"
    )

    time.sleep(2)

Time ≈ 6 seconds


Multithreaded Execution

import threading
import time

def download(file):

    print(
        f"Downloading {file}"
    )

    time.sleep(2)

for i in range(3):

    thread = threading.Thread(
        target=download,
        args=(i,)
    )

    thread.start()

Time ≈ 2 seconds


Selenium Automation Example

Run multiple test cases concurrently.

import threading

def run_test(test_name):

    print(
        f"Running {test_name}"
    )

thread1 = threading.Thread(
    target=run_test,
    args=("Login Test",)
)

thread2 = threading.Thread(
    target=run_test,
    args=("Checkout Test",)
)

thread1.start()
thread2.start()

Output

Running Login Test
Running Checkout Test

API Automation Example

Execute multiple API calls simultaneously.

import threading
import requests

def call_api(url):

    response = requests.get(url)

    print(
        response.status_code
    )

urls = [
    "https://api.example.com/users",
    "https://api.example.com/orders"
]

for url in urls:

    thread = threading.Thread(
        target=call_api,
        args=(url,)
    )

    thread.start()

Common Mistakes Beginners Make

Forgetting start()

Incorrect

thread = threading.Thread(
    target=worker
)

Thread is created but never runs.


Correct

thread.start()

Calling the Function Instead of Passing Reference

Incorrect

thread = threading.Thread(
    target=worker()
)

Function executes immediately.


Correct

thread = threading.Thread(
    target=worker
)

Forgetting join()

Incorrect

thread.start()

Main program may finish before thread completes.


Correct

thread.start()
thread.join()

Sharing Variables Unsafely

Multiple threads modifying the same variable may cause race conditions.

Use:

threading.Lock()

for synchronization.


Best Practices

Use Meaningful Thread Names

name="PaymentThread"

Use join() for Important Tasks

Wait for completion when necessary.


Keep Thread Tasks Small

Threads should perform a single responsibility.


Handle Exceptions Inside Threads

try:
    pass

except Exception as e:
    print(e)

Consider Thread Pools

For large applications use:

from concurrent.futures import ThreadPoolExecutor

Advantages of Creating Threads

  • Faster I/O operations

  • Better responsiveness

  • Concurrent task execution

  • Improved user experience

  • Efficient resource usage


Limitations

  • Global Interpreter Lock (GIL)

  • Synchronization complexity

  • Not ideal for CPU-intensive work


Conclusion

Creating threads is the first step in building concurrent Python applications. Using the threading module, developers can run multiple tasks simultaneously, improving performance and responsiveness for I/O-bound operations.

Whether you’re downloading files, calling APIs, processing data, or executing Selenium tests, understanding how to create and manage threads is an essential Python skill.


Frequently Asked Questions (FAQs)

Which module is used to create threads?

import threading

How do I create a thread?

thread = threading.Thread(
    target=my_function
)

How do I start a thread?

thread.start()

How do I wait for a thread to finish?

thread.join()

Can I pass arguments to a thread?

Yes.

args=(value,)

Key Takeaways

  • Threads enable concurrent execution within a process.

  • Python provides the threading module for thread creation.

  • Use Thread() to create threads.

  • Use start() to begin execution.

  • Use join() to wait for completion.

  • Arguments are passed using args.

  • Threads can be created using functions or custom classes.

  • Daemon threads run in the background.

  • Thread names improve debugging.

  • Threads are best suited for I/O-bound tasks such as Selenium automation, API calls, and file handling.