Cómo encontrar una identificación de hilo en Python

178

Tengo un programa Python de subprocesos múltiples y una función de utilidad writeLog(message)que escribe una marca de tiempo seguida del mensaje. Desafortunadamente, el archivo de registro resultante no indica qué hilo está generando qué mensaje.

Me gustaría writeLog()poder agregar algo al mensaje para identificar qué hilo lo está llamando. Obviamente, podría hacer que los hilos pasen esta información, pero eso sería mucho más trabajo. ¿Hay algún hilo equivalente al os.getpid()que podría usar?

Charles Anderson
fuente

Respuestas:

226

threading.get_ident()funciona, o threading.current_thread().ident(o threading.currentThread().identpara Python <2.6).

Nicholas Riley
fuente
3
Corregidos sus enlaces Nicholas. Recientemente me di cuenta de que si pasa el cursor sobre un título en los documentos, aparecerá un pequeño símbolo rojo a la derecha. Copie y pegue eso para obtener enlaces más específicos a los documentos :-)
Jon Cage
2
Tenga en cuenta que si está utilizando Jython, desea threading.currentThread()(camelCase, no camel_case) a partir de la versión 2.5.
Cam Jackson
3
@CharlesAnderson tenga cuidado, los documentos de Python en Thread.name dicen "name - Una cadena utilizada solo con fines de identificación. No tiene semántica. Se pueden dar varios hilos al mismo nombre. El constructor establece el nombre inicial".
drevicko
77
También tenga en cuenta que al menos en Python 2.5 y 2.6 en OS X, parece que hay un error que no threading.current_thread().identes apropiado None. Probablemente tenga sentido usarlo thread.get_ident()en Python 2 y threading.current_thread().identPython 3.
Nicholas Riley
55
Las versiones anteriores de mi respuesta mencionaron thread.get_ident()( threading.get_ident()se agregó en Python 3.3 - siga los enlaces a la documentación).
Nicholas Riley
67

Con el módulo de registro , puede agregar automáticamente el identificador de subproceso actual en cada entrada de registro. Solo use una de estas claves de mapeo LogRecord en su cadena de formato de registrador:

% (hilo) d: ID de hilo (si está disponible).

% (threadName) s: nombre del hilo (si está disponible).

y configure su controlador predeterminado con él:

logging.basicConfig(format="%(threadName)s:%(message)s")
kraymer
fuente
Estoy usando logger. Así que creo que su respuesta es la solución más simple. Pero estoy obteniendo <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 esto como un nombre de hilo. ¿Es ese el número de mi hilo que invocó
Ravi Shanker Reddy
22

La thread.get_ident()función devuelve un entero largo en Linux. No es realmente una identificación de hilo.

Utilizo este método para obtener realmente la identificación del hilo en 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)
brucexina
fuente
Esto se puede usar a veces pero no es portátil
Piyush Kansal
3
¿Podría editar esta respuesta para que siga siendo útil para los visitantes si el enlace se vuelve incorrecto?
josliber
¿Cómo envolver el método start () de mi clase de hilo para que pueda llenar mi self.pid con su pid cada vez que inicio el hilo? Intentó os.kill (pid) desde dentro del propio hilo, solo detiene todos los hilos, incluido el principal, debe hacerlo externamente el padre, pero ¿cómo obtener ese hijo pid del padre?
Rodrigo Formighieri
Como otros han insinuado, lamentablemente esto no funciona en algo como un Linux integrado que se ejecuta en un brazo de 32 bits.
Travis Griggs el
@TravisGriggs El concepto es portátil para Linux, incluidas las plataformas ARM de 32 bits. Solo necesita obtener el número de llamada correcto del sistema, que probablemente sea 224 en ARM y ARM64. Podría determinarse en tiempo de compilación o ejecución con un pequeño programa en C. Esto funciona para mí con Python 3.7 en un RPi. La respuesta de Jake Tesler es mejor si tienes Python 3.8, que aún no está presente en Raspbian 10.
TrentP
7

Vi ejemplos de ID de hilo como este:

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

La lista de documentos del módulo de subprocesosname también:

...

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

Puede obtener la identificación del hilo actual en ejecución. El ident podría ser reutilizado para otros hilos, si el hilo actual termina.

Cuando crea una instancia de Thread, se le da un nombre implícito al thread, que es el patrón: Thread-number

El nombre no tiene significado y el nombre no tiene que ser único. La identificación de todos los hilos en ejecución es única.

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 función threading.current_thread () devuelve el hilo actual en ejecución. Este objeto contiene toda la información del hilo.

Vigota
fuente
0

Creé múltiples hilos en Python, imprimí los objetos de hilo e imprimí la identificación usando la identvariable. Veo que todos los identificadores son iguales:

<Thread(Thread-1, stopped 140500807628544)>
<Thread(Thread-2, started 140500807628544)>
<Thread(Thread-3, started 140500807628544)>
shoaib shaikh
fuente
44
Supongo que se recicla, como identdicen los documentos : 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 manera similar a @brucexin, necesitaba obtener un identificador de subproceso a nivel del sistema operativo (que! = thread.get_ident()) Y usar algo como a continuación para no depender de números particulares y ser 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)                                                                  

y

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

...

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

Sin embargo, esto depende de Cython.

Kirr
fuente
Tenía la esperanza de que esta sería la versión multiplataforma que estaba buscando, pero recibo un error al respecto, invalid syntaxpuntero después de la externpalabra clave. Se me escapa algo. ¿Es importante que el código esté en un módulo separado y tenga la extensión pyx? ¿O es esto una cosa de (re) compilación?
Travis Griggs
Sí, esto depende de Cython y debe residir en un .pyxarchivo. Para "pitón puro", probablemente también se podría hacer algo similar con ctypes.
Kirir