How to obtain a Thread id in Python?
Asked Answered
E

8

284

I have a multi-threading Python program, and a utility function, writeLog(message), that writes out a timestamp followed by the message. Unfortunately, the resultant log file gives no indication of which thread is generating which message.

I would like writeLog() to be able to add something to the message to identify which thread is calling it. Obviously I could just make the threads pass this information in, but that would be a lot more work. Is there some thread equivalent of os.getpid() that I could use?

Edmundedmunda answered 28/5, 2009 at 9:4 Comment(0)
N
370

threading.get_ident() works, or threading.current_thread().ident (or threading.currentThread().ident for Python < 2.6).

Neeley answered 28/5, 2009 at 9:13 Comment(12)
Corrected your links Nicholas. I recently realised that if you hover over a title in the docs a little red symbol appears to the right. Copy+paste that for more specific links to the docs :-)Transponder
Thanks. I was wondering where the permalinks had got to in the new documentation format.Neeley
Note that if you're using Jython, you want threading.currentThread() (camelCase, not camel_case) as of version 2.5.Callum
@CharlesAnderson beware, the python docs on Thread.name say "name - A string used for identification purposes only. It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor."Fullback
Also note that at least in Python 2.5 and 2.6 on OS X, there seems to be a bug where threading.current_thread().ident is inappropriately None. Probably makes sense just to use thread.get_ident() in Python 2 and threading.current_thread().ident in Python 3.Neeley
Previous versions of my answer did mention thread.get_ident() (threading.get_ident() was added in Python 3.3 — follow the links to the documentation).Neeley
@NicholasRiley - What about for Python 3.0? Or 3.0 - 3.2, I should say, before .get_ident() was added...Maria
Ah, it looks like threading.current_thread().ident would be the way to go for Py3.0-3.2...Maria
Is it possible to retreive native_id as well?Dalessandro
p.s. - threading.current_thread().ident works for my on python2.7 on OSXLanettelaney
Thank you. In case I have multiple threads running under the same thread, how do I know the ID of one of them please?Saturation
@Saturation Do you mean you are in a system where multiple Python threads run under a single OS thread? I am not aware of any Python implementations where this is the case. Please see https://mcmap.net/q/110026/-what-is-a-python-threadNeeley
T
99

Using the logging module you can automatically add the current thread identifier in each log entry. Just use one of these LogRecord mapping keys in your logger format string:

%(thread)d : Thread ID (if available).

%(threadName)s : Thread name (if available).

and set up your default handler with it:

logging.basicConfig(format="%(threadName)s:%(message)s")
Tameratamerlane answered 1/3, 2010 at 17:19 Comment(3)
I am using logger. So I think you answer is the simplest solution. But I am getting <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 this as a thread name. Is that two is my thread number which invokedReversible
the PID seems to be needed in some cases to make it somewhat unique, at least (pyspark). So combining PID and thread-id seems to do the job: "%(thread)d-%(process)d"Disjunction
Thank you. In case I have multiple threads running under the same thread, how do I know the ID of one of them please?Saturation
F
47

This functionality is now supported by Python 3.8+ :)

You can now use: threading.get_native_id()

https://github.com/python/cpython/commit/4959c33d2555b89b494c678d99be81a65ee864b0

https://github.com/python/cpython/pull/11993

Floeter answered 12/5, 2019 at 17:26 Comment(3)
It is important to note that .get_ident() is a number assigned by the Python interpreter and .get_native_id() is the actual Thread ID that the kernel assigns to the thread when this is created.Pino
This worked perfectly as an alternative to brucexin's answer, which didn't work on some older machinesLiris
Note: If you spawn a secondary thread in a C++ extension, and callback into a Python function from there, they will report the same system thread id with this method, making that threading easy to follow across those layers!Helping
T
34

The threading.get_ident() function returns a long integer on Linux. It's not really a thread id.

I use this method to really get the thread id on Linux:

import ctypes
libc = ctypes.cdll.LoadLibrary('libc.so.6')

# System dependent, see e.g. /usr/include/x86_64-linux-gnu/asm/unistd_64.h
SYS_gettid = 186

def getThreadId():
   """Returns OS thread id - Specific to Linux"""
   return libc.syscall(SYS_gettid)
Teresetereshkova answered 23/2, 2012 at 9:17 Comment(6)
This can be used sometimes but is not portableKlarrisa
Could you please edit this answer so it will continue to be useful to visitors if the link becomes bad?Chaperon
how to wrap the start() method of my thread class so it can fill my self.pid with it's pid everytime I launch the thread? Tried os.kill(pid) from inside the own thread, it just stops all the threads including the main, must be done externally by the parent, but how to get that child pid from the parent?Hessenassau
As others have hinted, this sadly does not work on something like an embedded linux running on a 32 bit Arm.Tion
@TravisGriggs The concept is portable to Linux, including 32 bit ARM platforms. You just need to get the correct system call number, which is probably going to be 224 on ARM and ARM64. It could be determined at build or run time with a small C program. This works for me with Python 3.7 on an RPi. Jake Tesler's answer is better if you have Python 3.8, which is not present in Raspbian 10 yet.Padriac
@TravisGriggs You can also do something like "grep -ri SYS_gettid /usr/include/" to find the ID of your sys call.Unequaled
M
22

You can get the ident of the current running thread. The ident could be reused for other threads, if the current thread ends.

When you crate an instance of Thread, a name is given implicit to the thread, which is the pattern: Thread-number

The name has no meaning and the name don't have to be unique. The ident of all running threads is unique.

import threading


def worker():
    print(threading.current_thread().name)
    print(threading.get_ident())


threading.Thread(target=worker).start()
threading.Thread(target=worker, name='foo').start()

The function threading.current_thread() returns the current running thread. This object holds the whole information of the thread.

Mabel answered 8/3, 2019 at 9:46 Comment(1)
Thank you. In case I have multiple threads running under the same thread, how do I know the ID of one of them please?Saturation
M
7

I saw examples of thread IDs like this:

class myThread(threading.Thread):
    def __init__(self, threadID, name, counter):
        self.threadID = threadID
        ...

The threading module docs lists name attribute as well:

...

A thread has a name. 
The name can be passed to the constructor, 
and read or changed through the name attribute.

...

Thread.name

A string used for identification purposes only. 
It has no semantics. Multiple threads may
be given the same name. The initial name is set by the constructor.
Madagascar answered 28/5, 2009 at 9:11 Comment(1)
Thank you. In case I have multiple threads running under the same thread, how do I know the ID of one of them please?Saturation
P
0

I created multiple threads in Python, I printed the thread objects, and I printed the id using the ident variable. I see all the ids are same:

<Thread(Thread-1, stopped 140500807628544)>
<Thread(Thread-2, started 140500807628544)>
<Thread(Thread-3, started 140500807628544)>
Parental answered 19/6, 2015 at 5:31 Comment(1)
I guess it is recycled, as the docs for ident say: Thread identifiers may be recycled when a thread exits and another thread is created. docs.python.org/2/library/threading.html#threading.Thread.identHindmost
W
0

Similarly to @brucexin I needed to get OS-level thread identifier (which != thread.get_ident()) and use something like below not to depend on particular numbers and being amd64-only:

---- 8< ---- (xos.pyx)
"""module xos complements standard module os""" 

cdef extern from "<sys/syscall.h>":                                                             
    long syscall(long number, ...)                                                              
    const int SYS_gettid                                                                        

# gettid returns current OS thread identifier.                                                  
def gettid():                                                                                   
    return syscall(SYS_gettid)                                                                  

and

---- 8< ---- (test.py)
import pyximport; pyximport.install()
import xos

...

print 'my tid: %d' % xos.gettid()

this depends on Cython though.

Winifredwinikka answered 7/3, 2018 at 13:4 Comment(2)
I was hopeful this would be cross platform version I was looking for, but I get an error on this, invalid syntax pointer after extern keyword. Is there something I'm missing. Is it important that the code be in a separate module and have the pyx extension? Or is this a (re)compile thing?Tion
Yes, this depends on Cython and should reside in a .pyx file. For "pure python" probably something similar could be done with ctypes too.Winifredwinikka

© 2022 - 2024 — McMap. All rights reserved.