如何在Python中获取线程ID?

How to obtain a Thread id in Python?

提问人:Charles Anderson 提问时间:5/28/2009 最后编辑:ivanleonczCharles Anderson 更新时间:10/19/2023 访问量:363345

问:

我有一个多线程 Python 程序和一个实用程序函数,它写出一个时间戳,然后是消息。遗憾的是,生成的日志文件没有指示哪个线程正在生成哪个消息。writeLog(message)

我希望能够在消息中添加一些东西,以确定哪个线程正在调用它。显然,我可以让线程传递这些信息,但那将是更多的工作。有没有一些等效于我可以使用的线程?writeLog()os.getpid()

多线程 python-logging

评论


答:

7赞 miku 5/28/2009 #1

我看到了这样的线程 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.

评论

0赞 Avv 11/1/2022
谢谢。如果我有多个线程在同一线程下运行,我如何知道其中一个线程的 ID?
363赞 Nicholas Riley 5/28/2009 #2

threading.get_ident() 有效,或者 threading.current_thread().ident(或用于 Python < 2.6)。threading.currentThread().ident

评论

4赞 Jon Cage 5/28/2009
更正了您的链接尼古拉斯。我最近意识到,如果您将鼠标悬停在文档中的标题上,右侧会出现一个小红色符号。复制+粘贴以获取更具体的文档链接:-)
2赞 Cam Jackson 8/31/2011
请注意,如果您使用的是 Jython,则需要 (camelCase,而不是 camel_case) 从 2.5 版本开始。threading.currentThread()
4赞 drevicko 12/4/2012
@CharlesAnderson注意,Thread.name 上的 python 文档会说“name - 仅用于识别目的的字符串。它没有语义。多个线程可以被赋予相同的名称。初始名称由构造函数设置。
7赞 Nicholas Riley 12/4/2012
另请注意,至少在OS X上的Python 2.5和2.6中,似乎存在一个错误,其中不合适。可能在 Python 2 和 Python 3 中使用是有意义的。threading.current_thread().identNonethread.get_ident()threading.current_thread().ident
6赞 Nicholas Riley 1/15/2017
我的答案的先前版本确实提到了(在 Python 3.3 中添加 - 点击文档链接)。thread.get_ident()threading.get_ident()
98赞 kraymer 3/2/2010 #3

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

%(螺纹)d :线程 ID(如果可用)。

%(线程名称)s :线程名称(如果可用)。

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

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

评论

1赞 Ravi Shanker Reddy 5/30/2017
我正在使用记录器。所以我认为你的回答是最简单的解决方案。但我把它作为一个线程名称。是不是两个是我调用的线程号<concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2
0赞 selle 9/29/2022
在某些情况下,似乎需要 PID 来使其具有某种独特性,至少是这样 (pyspark)。因此,将 PID 和 thread-id 结合起来似乎可以完成这项工作:“%(thread)d-%(process)d”
0赞 Avv 11/1/2022
谢谢。如果我有多个线程在同一线程下运行,我如何知道其中一个线程的 ID?
33赞 brucexin 2/23/2012 #4

该函数在 Linux 上返回一个长整数。它不是真正的线程 ID。threading.get_ident()

我使用这种方法在 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)

评论

0赞 Piyush Kansal 2/26/2012
这有时可以使用,但不能移植
3赞 josliber 6/29/2016
您能否编辑此答案,以便在链接变坏时继续对访问者有用?
0赞 Rodrigo Formighieri 2/27/2019
如何包装我的线程类的 start() 方法,以便它可以在每次启动线程时用它的 pid 填充我的 self.pid?从自己的线程内部尝试了os.kill(pid),它只是停止了包括主线程在内的所有线程,必须由父线程在外部完成,但是如何从父线程中获取该子线程?
0赞 Travis Griggs 9/24/2019
正如其他人所暗示的那样,可悲的是,这在 32 位 Arm 上运行的嵌入式 linux 之类的东西上不起作用。
1赞 TrentP 12/4/2019
@TravisGriggs 该概念可移植到 Linux,包括 32 位 ARM 平台。您只需要获取正确的系统调用号,在 ARM 和 ARM64 上可能是 224。它可以在构建或运行时使用小型 C 程序确定。这对我在 RPi 上使用 Python 3.7 有效。如果你有 Python 3.8,Jake Tesler 的答案会更好,而 Raspbian 10 中还没有。
0赞 shoaib shaikh 6/19/2015 #5

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

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

评论

6赞 oblalex 12/14/2015
我想它是回收的,正如文档所说:docs.python.org/2/library/threading.html#threading.Thread.identidentThread identifiers may be recycled when a thread exits and another thread is created.
0赞 kirr 3/7/2018 #6

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

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

评论

0赞 Travis Griggs 9/24/2019
我希望这将是我正在寻找的跨平台版本,但我在关键字后出现错误。我错过了什么吗?代码位于单独的模块中并具有 pyx 扩展名是否重要?或者这是一个(重新)编译的东西?invalid syntaxextern
0赞 kirr 9/24/2019
是的,这取决于 Cython,并且应该驻留在文件中。对于“纯 python”,可能也可以用 ctypes 做类似的事情。.pyx
22赞 DeaD_EyE 3/8/2019 #7

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

当您创建 Thread 的实例时,会为线程提供一个隐式名称,即模式:Thread-number

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

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() 返回当前正在运行的线程。此对象包含线程的全部信息。

评论

1赞 Avv 11/1/2022
谢谢。如果我有多个线程在同一线程下运行,我如何知道其中一个线程的 ID?
43赞 Jake Tesler 5/13/2019 #8

Python 3.8+ 现在支持此功能:)

您现在可以使用:threading.get_native_id()

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

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

评论

3赞 Pavel Razgovorov 12/7/2022
需要注意的是,这是 Python 解释器分配的数字,是内核在创建线程时分配给线程的实际线程 ID。.get_ident().get_native_id()
0赞 MANA624 1/24/2023
这完美地替代了brucexin的答案,后者在一些较旧的机器上不起作用
0赞 BuvinJ 7/20/2023
注意:如果您在 C++ 扩展中生成辅助线程,并从那里回调到 Python 函数中,它们将使用此方法报告相同的系统线程 ID,从而使该线程易于跨这些层跟踪!