如何在Python中找到线程ID


176

我有一个多线程Python程序和一个实用程序函数, writeLog(message),该写出时间戳记和消息。不幸的是,结果日志文件没有给出哪个线程正在生成哪个消息的指示。

我希望writeLog()能够在消息中添加一些内容,以标识哪个线程正在调用它。显然,我可以使线程将这些信息传递进来,但这将需要更多工作。是否有一些os.getpid()我可以使用的等效线程?

Answers:


224

threading.get_ident(),或threading.current_thread().ident(或(threading.currentThread().ident对于python <2.6)。


3
更正了您的链接尼古拉斯。我最近意识到,如果将鼠标悬停在文档中的标题上方,则会在右侧显示一个红色的小符号。复制并粘贴该链接,以获得指向文档的更具体链接:-)
乔恩·凯奇

2
请注意,如果您使用的是Jython,则threading.currentThread()要从2.5版开始(camelCase,而不是camel_case)。
坎·杰克逊

3
@CharlesAnderson提防,对Python文档Thread.name说“的名字-仅用于标识目的的字符串,它没有语义。多个线程可以被赋予相同的名称。最初的名称是由构造函数设置。”
drevicko

7
还要注意的是,至少在Python 2.5和2.6在OS X上,似乎有哪里的错误threading.current_thread().ident是不恰当的None。可能是有道理只使用thread.get_ident()在Python 2和threading.current_thread().identPython中的3
尼古拉斯·莱利

5
我的答案的先前版本确实提到了thread.get_ident()threading.get_ident()已在Python 3.3中添加-请点击文档链接)。
Nicholas Riley

67

使用日志记录模块,您可以在每个日志条目中自动添加当前线程标识符。只需在记录器格式字符串中使用以下LogRecord映射键之一:

%(thread)d: 线程ID(如果有)。

%(threadName)s: 线程名称(如果有)。

并使用它设置默认处理程序:

logging.basicConfig(format="%(threadName)s:%(message)s")

我正在使用记录器。所以我认为您的答案是最简单的解决方案。但是我<concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 将此作为线程名称。那是我调用的线程号吗?
Ravi Shanker Reddy

22

thread.get_ident()函数在Linux上返回一个长整数。这实际上不是线程ID。

我使用这种方法来真正获取Linux上的线程ID:

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)

有时可以使用它,但不能移植
Piyush Kansal 2012年

3
您能否编辑此答案,这样如果链接变坏,它将继续对访问者有用?
josliber

如何包装线程类的start()方法,以便每次启动线程时都可以用pid填充self.pid?从自己的线程内部尝试过os.kill(pid),它只是停止了包括主线程在内的所有线程,必须由父级在外部完成,但是如何从父级获取该子级pid?
Rodrigo Formighieri,

正如其他人所暗示的那样,令人遗憾的是,这不适用于在32位Arm上运行的嵌入式Linux之类的东西。
特拉维斯·格里格斯

@TravisGriggs此概念可移植到Linux,包括32位ARM平台。您只需要获取正确的系统调用号,在ARM和ARM64上可能会是224。它可以在构建或运行时使用小型C程序确定。这适用于我在RPi上使用Python 3.7的情况。如果您拥有Raspbian 10中尚未提供的Python 3.8,则Jake Tesler的答案会更好。
TrentP


7

我看到了这样的线程ID的示例:

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

线程模块文档列表name属性,以及:

...

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.

6

您可以获得当前正在运行的线程的标识。如果当前线程结束,则该标识可以重用于其他线程。

创建线程实例时,将为该线程隐式指定一个名称,即模式:线程号

名称没有意义,名称不必唯一。所有正在运行的线程的标识都是唯一的。

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()

函数threading.current_thread()返回当前正在运行的线程。该对象保存线程的全部信息。


0

我在Python中创建了多个线程,打印了线程对象,并使用ident变量打印了id 。我看到所有ID都一样:

<Thread(Thread-1, stopped 140500807628544)>
<Thread(Thread-2, started 140500807628544)>
<Thread(Thread-3, started 140500807628544)>

4
我猜它已经被回收了,就像文档ident所说的那样: Thread identifiers may be recycled when a thread exits and another thread is created. docs.python.org/2/library/threading.html#threading.Thread.ident
oblalex

0

与@brucexin类似,我需要获取操作系统级别的线程标识符(!= thread.get_ident()),并使用如下所示的内容来不依赖于特定的数字并且仅使用amd64:

---- 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)                                                                  

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

...

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

这取决于Cython。


我希望这将是我正在寻找的跨平台版本,但是我在此问题上遇到了一个错误,invalid syntax指向extern关键字的指针。有什么我想念的吗?将代码放在单独的模块中并具有pyx扩展是否重要?还是这是(重新)编译的东西?
特拉维斯·格里格斯

是的,这取决于Cython,应该驻留在.pyx文件中。对于“纯python”,可能也可以使用ctypes做类似的事情。
kirr,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.