How to Get a Thread ID in Python?

Background and Problem Description

Multi-threading allows you to run your program concurrently. You can achieve this by using threads.

💡 Definition: In simple terms, a thread is a set of instructions that can be executed independently to perform some task. One thread might run a part of the program while the other runs another part. We can achieve multi-threading in Python using a standard Python library called threading.

Consider the following example. This program creates two threads and executes them.

import logging
import threading
import time

def thread_function():
  logging.info("thread_function : Thread in action")
  time.sleep(2)

if __name__=="__main__" :
  #Set up the default handler
  logging.basicConfig(format="%(message)s", level=logging.INFO)

  # Create the threads
  logging.info("main  : Creating the threads")
  t1= threading.Thread(target=thread_function)
  t2= threading.Thread(target=thread_function)

  # Run the threads
  logging.info("main  : Calling the threads")
  t1.start()
  t2.start()

  logging.info("main  : Completed executing threads")

Output:

main  : Creating the threads
main  : Calling the threads
thread_function : Thread in action
thread_function : Thread in action
main  : Completed executing threads

🧩 Exercise: Do you see a problem?

Both the threads execute. But when you look at the log messages, it is hard to identify the thread instance that is running.

In complex programs, it is of utmost importance to know the instance of the thread that is running. If an error arises, these messages come in handy to understand where the problem lies.

To solve this problem, pass an argument explicitly to identify the threads. We can do it while creating an instance of a thread, as shown below.

threading.Thread(target=thread_function, args=('<name>',))

In the below code snippet, we pass t1, t2 as names for the threads.

import logging
import threading
import time

def thread_function(name):
  logging.info("%s : Thread in action", name)
  time.sleep(2)

if __name__=="__main__" :
  # Set up the default handler
  logging.basicConfig(format="%(message)s", level=logging.INFO)

  # Create the threads and explicitly passing a name
  logging.info("main  : Creating the threads")
  t1= threading.Thread(target=thread_function, args=('t1',))
  t2= threading.Thread(target=thread_function, args=('t2',))

  # Run the threads
  logging.info("main  : Calling the threads")
  t1.start()
  t2.start()

  logging.info("main  : Completed executing threads")

As you can see, instead of thread_function, we see the names t1, t2 in the logs.

main  : Creating the threads
main  : Calling the threads
t1 : Thread in action
t2 : Thread in action
main  : Completed executing threads

It solves the problem to some extent. 

But imagine a complex program with several threads. Passing a name to every thread is an overhead. Not just that, we have to manually check and ensure that we are passing the unique values.

So what do we do? Well, we can make use of the Thread-ID to identify a thread. Thread ID would be unique for all the active threads.

If you are wondering how to obtain the thread ID, read along. This guide covers different ways of getting a thread ID in Python.

Method 1: Using threading.get_ident() function

In Python 3.3+, you can use threading.get_ident() function to obtain the thread ID of a thread.

threading.get_ident() returns the thread ID of the current thread. It is a non-zero integer. The thread-specific data is stored in a dictionary format. The ID returned from thread_get_ident() is the key value used to index this dictionary.

💡 Resource: To find out more about this function, check this link.

Alternatively, you can also use threading.current_thread().ident

In the below code snippet, we use threading.get_ident() to obtain the thread IDs.

import logging
import threading
import time

def thread_function():
  # Use threading.get_ident() to show the Thread ID
  logging.info("%d : Thread in action",threading.get_ident())
  time.sleep(2)

if __name__=="__main__" :
  # Set up the default handler
  logging.basicConfig(format="%(message)s ", level=logging.INFO)

  # Creating the threads
  logging.info("main : Creating the threads")
  t1= threading.Thread(target=thread_function)
  t2= threading.Thread(target=thread_function)

  # Run the threads
  logging.info("main : Calling the threads")
  t1.start()
  t2.start()

  logging.info("main  : Completed executing threads")

As you can see, instead of the thread names (t1, t2), a unique identifier is returned for each thread.

main : Creating the threads
main : Calling the threads
6264 : Thread in action
17764 : Thread in action
main  : Completed executing threads

Method 2: Using threading.get_native_id() function

In Python 3.8+, you can use threading.get_native_id() function to obtain the thread ID.

threading.get_native_id() returns the thread ID of the current thread as assigned by the kernel of a native operating system. It is a non-zero integer. This value identifies the current thread throughout the system.

💡 Resource: To find out more about this function, check this link.

Alternatively, you can also use threading.current_thread().native_id

In the below code snippet, we use threading.get_native_id()  to obtain the thread IDs.

import logging
import threading
import time

def thread_function():
   # Use threading.get_native_id() to show the Thread ID
   logging.info("%d : Thread in action",threading.get_native_id())
   time.sleep(2)

if __name__=="__main__" :
   #Set up the default handler
   logging.basicConfig(format="%(message)s ", level=logging.INFO)

   # Creating the threads
   logging.info("main : Creating the threads")
   t1= threading.Thread(target=thread_function)
   t2= threading.Thread(target=thread_function)

   # Run the threads
   logging.info("main : Calling the threads")
   t1.start()
   t2.start()

   logging.info("main  : Completed executing threads")

As you can see, instead of the thread names (t1, t2), a unique identifier is returned for each thread.

main : Creating the threads
main : Calling the threads
12268 : Thread in action
8588 : Thread in action
main  : Completed executing threads

Method 3: Use the logging module to display its Thread ID

The logging module enables you to add the thread id in the log message. We can add the %(thread)d mapping key in the logger format string as shown below.

logging.basicConfig(format="%(thread)d : %(message)s ", level=logging.INFO)

In the below code snippet, we use the %(thread)d mapping key to display the Thread ID in the log messages.

import logging
import threading
import time

def thread_function():
  logging.info("Thread in action")
  time.sleep(2)

if __name__=="__main__" :
  #Set up the default handler
  logging.basicConfig(format="%(thread)d : %(message)s ", level=logging.INFO)

  # Create the threads
  logging.info("main  : Creating the threads")
  t1= threading.Thread(target=thread_function)
  t2= threading.Thread(target=thread_function)

  # Run the threads
  logging.info("main  : Calling the threads")
  t1.start()
  t2.start()

  logging.info("main  : Completed executing threads")

As you can see, a unique identifier is added to identify the threads.

6868 : main  : Creating the threads
6868 : main  : Calling the threads
6508 : Thread in action
1512 : Thread in action
6868 : main  : Completed executing threads

Summary

In this article, we have seen three different ways of getting the thread identifiers for a thread. We hope this guide has been informative. Please subscribe to us to receive more interesting content. Thank you for Reading.

Happy Pythoning!