So finden Sie eine Thread-ID in Python


176

Ich habe ein Multithreading-Python-Programm und eine Dienstprogrammfunktion, writeLog(message)die einen Zeitstempel gefolgt von der Nachricht schreibt. Leider gibt die resultierende Protokolldatei keinen Hinweis darauf, welcher Thread welche Nachricht generiert.

Ich möchte writeLog()in der Lage sein, der Nachricht etwas hinzuzufügen, um zu identifizieren, welcher Thread sie aufruft. Natürlich könnte ich die Threads dazu bringen, diese Informationen weiterzugeben, aber das wäre viel mehr Arbeit. Gibt es ein Thread-Äquivalent dazu os.getpid(), das ich verwenden könnte?

Antworten:


224

threading.get_ident()funktioniert oder threading.current_thread().ident(oder threading.currentThread().identfür Python <2.6).


3
Korrigierte deine Links Nicholas. Ich habe kürzlich festgestellt, dass rechts ein kleines rotes Symbol angezeigt wird, wenn Sie mit der Maus über einen Titel in den Dokumenten fahren. Kopieren Sie + fügen Sie das ein, um genauere Links zu den Dokumenten zu erhalten :-)
Jon Cage

2
Wenn Sie Jython verwenden, möchten Sie threading.currentThread()(camelCase, nicht camel_case) ab Version 2.5.
Cam Jackson

3
@CharlesAnderson Vorsicht, die Python-Dokumente in Thread.name sagen "name - Eine Zeichenfolge, die nur zu Identifikationszwecken verwendet wird. Sie hat keine Semantik. Mehrere Threads können denselben Namen erhalten. Der ursprüngliche Name wird vom Konstruktor festgelegt."
Drevicko

7
Beachten Sie auch, dass zumindest in Python 2.5 und 2.6 unter OS X ein Fehler threading.current_thread().identauftritt, der unangemessen ist None. Wahrscheinlich macht es Sinn, nur thread.get_ident()in Python 2 und threading.current_thread().identin Python 3 zu verwenden.
Nicholas Riley

5
In früheren Versionen meiner Antwort wurde dies erwähnt thread.get_ident()( threading.get_ident()wurde in Python 3.3 hinzugefügt - folgen Sie den Links zur Dokumentation).
Nicholas Riley

67

Mit dem Protokollierungsmodul können Sie automatisch die aktuelle Thread-ID in jeden Protokolleintrag einfügen. Verwenden Sie einfach einen dieser LogRecord- Zuordnungsschlüssel in Ihrer Zeichenfolge im Logger-Format:

% (Thread) d: Thread-ID (falls verfügbar).

% (threadName) s: Threadname (falls verfügbar).

und richten Sie Ihren Standard-Handler damit ein:

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

Ich benutze Logger. Ich denke, Ihre Antwort ist die einfachste Lösung. Aber ich bekomme <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 das als Threadnamen. Ist das zwei ist meine Thread-Nummer, die aufgerufen hat
Ravi Shanker Reddy

22

Die thread.get_ident()Funktion gibt unter Linux eine lange Ganzzahl zurück. Es ist nicht wirklich eine Thread-ID.

Ich benutze diese Methode , um die Thread-ID unter Linux wirklich zu erhalten:

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)

Dies kann manchmal verwendet werden, ist aber nicht tragbar
Piyush Kansal

3
Könnten Sie diese Antwort bitte bearbeiten, damit sie für Besucher weiterhin nützlich ist, wenn der Link schlecht wird?
Josliber

Wie kann ich die start () -Methode meiner Thread-Klasse umbrechen, damit sie meine self.pid bei jedem Start des Threads mit ihrer pid füllen kann? Versucht os.kill (pid) aus dem eigenen Thread heraus, stoppt es nur alle Threads einschließlich des Haupt-Threads, muss extern vom Elternteil durchgeführt werden, aber wie bekommt man das Kind pid vom Elternteil?
Rodrigo Formighieri

Wie andere angedeutet haben, funktioniert dies leider nicht unter einem eingebetteten Linux, das auf einem 32-Bit-Arm ausgeführt wird.
Travis Griggs

@TravisGriggs Das Konzept ist auf Linux portierbar, einschließlich 32-Bit-ARM-Plattformen. Sie müssen nur die richtige Systemrufnummer erhalten, die auf ARM und ARM64 wahrscheinlich 224 sein wird. Sie kann zur Build- oder Laufzeit mit einem kleinen C-Programm ermittelt werden. Dies funktioniert bei mir mit Python 3.7 auf einem RPi. Jake Teslers Antwort ist besser, wenn Sie Python 3.8 haben, das in Raspbian 10 noch nicht vorhanden ist.
TrentP


7

Ich habe Beispiele für Thread-IDs wie diese gesehen:

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

Das Dokument des Threading-Moduls listet auch das nameAttribut auf:

...

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

Sie können die Identität des aktuell laufenden Threads abrufen. Die ID könnte für andere Threads wiederverwendet werden, wenn der aktuelle Thread endet.

Wenn Sie eine Instanz von Thread erstellen, wird dem Thread implizit ein Name zugewiesen. Dies ist das Muster: Thread-Nummer

Der Name hat keine Bedeutung und der Name muss nicht eindeutig sein. Die Identität aller laufenden Threads ist eindeutig.

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

Die Funktion threading.current_thread () gibt den aktuell laufenden Thread zurück. Dieses Objekt enthält die gesamten Informationen des Threads.


0

Ich habe in Python mehrere Threads erstellt, die Thread-Objekte gedruckt und die ID mithilfe der identVariablen gedruckt . Ich sehe, dass alle IDs gleich sind:

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

4
Ich denke, es wird recycelt, wie in den Dokumenten zum Beispiel angegeben 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

Ähnlich wie bei @brucexin musste ich eine Thread-ID auf Betriebssystemebene (welche! = thread.get_ident()) Abrufen und Folgendes verwenden, um nicht von bestimmten Zahlen abhängig zu sein und nur amd64 zu sein:

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

und

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

...

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

Dies hängt jedoch von Cython ab.


Ich hatte die Hoffnung, dass dies die plattformübergreifende Version sein würde, nach der ich gesucht habe, aber ich erhalte eine Fehlermeldung, invalid syntaxZeiger nach externSchlüsselwort. Fehlt mir etwas? Ist es wichtig, dass sich der Code in einem separaten Modul befindet und die pyx-Erweiterung hat? Oder ist das eine (Neu-) Kompilierungssache?
Travis Griggs

Ja, dies hängt von Cython ab und sollte sich in einer .pyxDatei befinden. Für "pure python" könnte wahrscheinlich etwas Ähnliches auch mit ctypes gemacht werden.
Kirr
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.