Come trovare un ID thread in Python


179

Ho un programma Python multi-thread e una funzione di utilità writeLog(message)che scrive un timestamp seguito dal messaggio. Sfortunatamente, il file di registro risultante non fornisce indicazioni su quale thread sta generando quale messaggio.

Vorrei writeLog()poter aggiungere qualcosa al messaggio per identificare quale thread lo sta chiamando. Ovviamente potrei semplicemente fare in modo che i thread passino queste informazioni, ma sarebbe molto più lavoro. Esiste un thread equivalente a os.getpid()quello che potrei usare?

Risposte:


227

threading.get_ident()funziona, o threading.current_thread().ident(o threading.currentThread().identper Python <2.6).


3
Corretti i tuoi collegamenti Nicholas. Di recente mi sono reso conto che se passi con il mouse sopra un titolo nei documenti, un piccolo simbolo rosso appare a destra. Copia + incolla quello per collegamenti più specifici ai documenti :-)
Jon Cage,

2
Nota che se stai usando Jython, vuoi threading.currentThread()(camelCase, non camel_case) dalla versione 2.5.
Cam Jackson,

3
@CharlesAnderson attenzione, i documenti di Python su Thread.name dicono "name - Una stringa usata solo a scopo identificativo. Non ha semantica. È possibile assegnare lo stesso nome a più thread. Il nome iniziale viene impostato dal costruttore."
drevicko,

7
Si noti inoltre che almeno in Python 2.5 e 2.6 su OS X, sembra che ci sia un bug in cui threading.current_thread().identè inappropriato None. Probabilmente ha senso usare solo thread.get_ident()in Python 2 e threading.current_thread().identin Python 3.
Nicholas Riley il

5
Le versioni precedenti di mia risposta ha fatto menzione thread.get_ident()( threading.get_ident()è stato aggiunto in Python 3.3 - seguire il link alla documentazione).
Nicholas Riley,

68

Utilizzando il modulo di registrazione è possibile aggiungere automaticamente l'identificatore del thread corrente in ogni voce del registro. Basta usare una di queste chiavi di mappatura LogRecord nella stringa del formato del logger:

% (thread) d: ID thread (se disponibile).

% (threadName) s: nome del thread (se disponibile).

e imposta il gestore predefinito con esso:

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

Sto usando il logger. Quindi penso che tu risponda è la soluzione più semplice. Ma sto ricevendo <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 questo come nome di thread. È quel due il mio numero di thread che ha invocato
Ravi Shanker Reddy

22

La thread.get_ident()funzione restituisce un numero intero lungo su Linux. Non è proprio un ID thread.

Uso questo metodo per ottenere davvero l'ID thread su 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)

Questo può essere usato a volte ma non è portatile
Piyush Kansal,

3
Potresti modificare questa risposta in modo che possa essere utile ai visitatori se il link diventa danneggiato?
josliber

come racchiudere il metodo start () della mia classe thread in modo che possa riempire il mio self.pid con il suo pid ogni volta che lancio il thread? Ho provato os.kill (pid) dall'interno del proprio thread, si ferma solo tutti i thread incluso il principale, deve essere fatto esternamente dal genitore, ma come ottenere quel pid figlio dal genitore?
Rodrigo Formighieri,

Come altri hanno suggerito, questo purtroppo non funziona su qualcosa come un Linux incorporato in esecuzione su un braccio a 32 bit.
Travis Griggs,

@TravisGriggs Il concetto è portabile su Linux, comprese le piattaforme ARM a 32 bit. Devi solo ottenere il numero di chiamata di sistema corretto, che probabilmente sarà 224 su ARM e ARM64. Potrebbe essere determinato in fase di compilazione o di esecuzione con un piccolo programma C. Questo funziona per me con Python 3.7 su un RPi. La risposta di Jake Tesler è migliore se hai Python 3.8, che non è ancora presente in Raspbian 10.
TrentP


7

Ho visto esempi di ID thread come questo:

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

Anche l' attributo elenca i documenti del modulo threadingname :

...

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.

7

È possibile ottenere l'ident del thread corrente corrente. L'ident potrebbe essere riutilizzato per altri thread, se il thread corrente termina.

Quando crei un'istanza di Thread, viene dato un nome implicito al thread, che è il modello: Thread-number

Il nome non ha significato e il nome non deve essere univoco. L'identità di tutti i thread in esecuzione è unica.

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 funzione threading.current_thread () restituisce il thread corrente in esecuzione. Questo oggetto contiene tutte le informazioni del thread.


0

Ho creato più thread in Python, ho stampato gli oggetti thread e ho stampato l'id usando la identvariabile. Vedo che tutti gli ID sono uguali:

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

4
Immagino che sia riciclato, come identdicono i documenti : 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

Analogamente a @brucexin, avevo bisogno di ottenere un identificatore di thread a livello di sistema operativo (che! = thread.get_ident()) E usare qualcosa come sotto per non dipendere da numeri particolari ed essere solo 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)                                                                  

e

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

...

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

questo dipende però da Cython.


Speravo che questa fosse la versione multipiattaforma che stavo cercando, ma ricevo un errore su questo, invalid syntaxpuntatore dopo externparola chiave. C'è qualcosa che mi manca. È importante che il codice sia in un modulo separato e abbia l'estensione pyx? O è una cosa (ri) compilare?
Travis Griggs,

Sì, questo dipende da Cython e dovrebbe risiedere in un .pyxfile. Per "puro pitone" probabilmente qualcosa di simile potrebbe essere fatto anche con i tipi.
Kirir,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.