Comment trouver un identifiant de thread en Python

179

J'ai un programme Python multi-thread et une fonction utilitaire writeLog(message), qui écrit un horodatage suivi du message. Malheureusement, le fichier journal résultant ne donne aucune indication sur quel thread génère quel message.

Je voudrais writeLog()pouvoir ajouter quelque chose au message pour identifier quel thread l'appelle. Évidemment, je pourrais simplement faire en sorte que les threads transmettent ces informations, mais ce serait beaucoup plus de travail. Y a-t-il un équivalent de thread os.getpid()que je pourrais utiliser?

Charles Anderson
la source

Réponses:

227

threading.get_ident()fonctionne, ou threading.current_thread().ident(ou threading.currentThread().identpour Python <2.6).

Nicholas Riley
la source
3
Correction de vos liens Nicholas. J'ai récemment réalisé que si vous survolez un titre dans la documentation, un petit symbole rouge apparaît à droite. Copiez et collez cela pour des liens plus spécifiques vers la documentation :-)
Jon Cage
2
Notez que si vous utilisez Jython, vous voulez threading.currentThread()(camelCase, pas camel_case) à partir de la version 2.5.
Cam Jackson
3
@CharlesAnderson attention, la documentation python sur Thread.name dit "nom - Une chaîne utilisée à des fins d'identification uniquement. Elle n'a pas de sémantique. Plusieurs threads peuvent avoir le même nom. Le nom initial est défini par le constructeur."
drevicko
7
Notez également qu'au moins dans Python 2.5 et 2.6 sur OS X, il semble y avoir un bogue là où threading.current_thread().identc'est inapproprié None. Il est probablement logique de l'utiliser simplement thread.get_ident()en Python 2 et threading.current_thread().identen Python 3.
Nicholas Riley
5
Les versions précédentes de ma réponse ont mentionné thread.get_ident()(a threading.get_ident()été ajouté dans Python 3.3 - suivez les liens vers la documentation).
Nicholas Riley le
68

En utilisant le module de journalisation, vous pouvez ajouter automatiquement l'identificateur de thread actuel dans chaque entrée de journal. Utilisez simplement l'une de ces clés de mappage LogRecord dans la chaîne de format de votre enregistreur:

% (thread) d: ID de thread (si disponible).

% (threadName) s: nom du thread (si disponible).

et configurez votre gestionnaire par défaut avec:

logging.basicConfig(format="%(threadName)s:%(message)s")
kraymer
la source
J'utilise un enregistreur. Je pense donc que votre réponse est la solution la plus simple. Mais j'obtiens <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 cela comme un nom de fil. Est-ce que deux est mon numéro de fil qui a invoqué
Ravi Shanker Reddy
22

La thread.get_ident()fonction renvoie un entier long sous Linux. Ce n'est pas vraiment un identifiant de thread.

J'utilise cette méthode pour vraiment obtenir l'identifiant du thread sous 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)
brucexine
la source
Cela peut être utilisé parfois mais n'est pas portable
Piyush Kansal
3
Pourriez-vous modifier cette réponse pour qu'elle continue d'être utile aux visiteurs si le lien devient défectueux?
josliber
comment envelopper la méthode start () de ma classe de thread afin qu'elle puisse remplir mon self.pid avec son pid à chaque fois que je lance le thread? J'ai essayé os.kill (pid) depuis l'intérieur du propre thread, il arrête juste tous les threads, y compris le principal, doit être effectué en externe par le parent, mais comment obtenir ce pid enfant du parent?
Rodrigo Formighieri
Comme d'autres l'ont laissé entendre, cela ne fonctionne malheureusement pas sur quelque chose comme un Linux intégré fonctionnant sur un Arm 32 bits.
Travis Griggs
@TravisGriggs Le concept est portable sous Linux, y compris les plates-formes ARM 32 bits. Vous avez juste besoin d'obtenir le bon numéro d'appel système, qui sera probablement 224 sur ARM et ARM64. Il peut être déterminé au moment de la construction ou de l'exécution avec un petit programme C. Cela fonctionne pour moi avec Python 3.7 sur un RPi. La réponse de Jake Tesler est meilleure si vous avez Python 3.8, qui n'est pas encore présent dans Raspbian 10.
TrentP
7

J'ai vu des exemples d'ID de thread comme celui-ci:

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

Le module de threading docs répertorie également l' nameattribut:

...

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.
Miku
la source
7

Vous pouvez obtenir l'identifiant du thread en cours d'exécution. L'ident peut être réutilisé pour d'autres threads, si le thread actuel se termine.

Lorsque vous créez une instance de Thread, un nom est donné implicitement au thread, qui est le modèle: Thread-number

Le nom n'a aucune signification et le nom n'a pas besoin d'être unique. L'identifiant de tous les threads en cours d'exécution est 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()

La fonction threading.current_thread () renvoie le thread en cours d'exécution. Cet objet contient toutes les informations du fil.

DeaD_EyE
la source
0

J'ai créé plusieurs threads en Python, j'ai imprimé les objets thread et j'ai imprimé l'id en utilisant la identvariable. Je vois que tous les identifiants sont identiques:

<Thread(Thread-1, stopped 140500807628544)>
<Thread(Thread-2, started 140500807628544)>
<Thread(Thread-3, started 140500807628544)>
shoaib shaikh
la source
5
Je suppose qu'il est recyclé, comme le identdisent les documents : 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

De la même manière que @brucexin, j'avais besoin d'obtenir un identifiant de thread au niveau du système d'exploitation (qui! = thread.get_ident()) Et d'utiliser quelque chose comme ci-dessous pour ne pas dépendre de nombres particuliers et être uniquement 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)                                                                  

et

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

...

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

cela dépend cependant de Cython.

kirr
la source
J'espérais que ce serait la version multiplateforme que je recherchais, mais j'obtiens une erreur à ce sujet, invalid syntaxpointeur après externmot-clé. Y a-t-il quelque chose qui me manque? Est-il important que le code soit dans un module séparé et ait l'extension pyx? Ou est-ce une (re) compilation?
Travis Griggs
Oui, cela dépend de Cython et devrait résider dans un .pyxfichier. Pour "python pur", quelque chose de similaire pourrait probablement être fait avec les ctypes.
kirr le