Cara menemukan id utas dengan Python

178

Saya memiliki program Python multi-threading, dan fungsi utilitas writeLog(message),, yang menulis timestamp diikuti oleh pesan. Sayangnya, file log yang dihasilkan tidak memberikan indikasi thread mana yang menghasilkan pesan mana.

Saya ingin writeLog()dapat menambahkan sesuatu ke pesan untuk mengidentifikasi utas yang memanggilnya. Jelas saya bisa membuat utas menyampaikan informasi ini, tetapi itu akan menjadi lebih banyak pekerjaan. Apakah ada beberapa thread yang setara os.getpid()yang bisa saya gunakan?

Charles Anderson
sumber

Jawaban:

226

threading.get_ident()bekerja, atau threading.current_thread().ident(atau threading.currentThread().identuntuk Python <2.6).

Nicholas Riley
sumber
3
Memperbaiki tautan Anda, Nicholas. Saya baru-baru menyadari bahwa jika Anda mengarahkan kursor ke judul dalam dokumen, simbol merah kecil muncul di sebelah kanan. Salin + rekatkan itu untuk tautan yang lebih spesifik ke dokumen :-)
Jon Cage
2
Perhatikan bahwa jika Anda menggunakan Jython, Anda ingin threading.currentThread()(camelCase, bukan camel_case) pada versi 2.5.
Cam Jackson
3
@CharlesAnderson berhati-hatilah, dokumen python di Thread.name mengatakan "nama - string yang digunakan untuk tujuan identifikasi saja. Tidak memiliki semantik. Beberapa utas mungkin diberi nama yang sama. Nama awal ditetapkan oleh konstruktor."
drevicko
7
Perhatikan juga bahwa setidaknya dalam Python 2.5 dan 2.6 pada OS X, tampaknya ada bug di mana threading.current_thread().identtidak tepat None. Mungkin masuk akal hanya untuk digunakan thread.get_ident()dalam Python 2 dan threading.current_thread().identPython 3.
Nicholas Riley
5
Versi sebelumnya dari jawaban saya lakukan menyebutkan thread.get_ident()( threading.get_ident()ditambahkan dengan Python 3.3 - ikuti link ke dokumentasi).
Nicholas Riley
67

Menggunakan modul logging Anda dapat secara otomatis menambahkan pengenal utas saat ini di setiap entri log. Cukup gunakan salah satu kunci pemetaan LogRecord ini dalam string format logger Anda:

% (utas) d: ID utas (jika tersedia).

% (threadName) s: Nama utas (jika tersedia).

dan atur handler default Anda dengannya:

logging.basicConfig(format="%(threadName)s:%(message)s")
kraymer
sumber
Saya menggunakan logger. Jadi saya pikir Anda menjawab adalah solusi paling sederhana. Tapi saya mendapatkan <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 ini sebagai nama utas. Apakah itu dua adalah nomor utas saya yang dipanggil
Ravi Shanker Reddy
22

The thread.get_ident()mengembalikan fungsi integer panjang di Linux. Ini bukan id utas.

Saya menggunakan metode ini untuk benar-benar mendapatkan id utas di 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)
brucexin
sumber
Ini dapat digunakan kadang-kadang tetapi tidak portabel
Piyush Kansal
3
Bisakah Anda mengedit jawaban ini sehingga akan terus bermanfaat bagi pengunjung jika tautannya menjadi buruk?
josliber
bagaimana cara membungkus metode start () dari kelas thread saya sehingga dapat mengisi self.pid dengan pid itu setiap kali saya meluncurkan thread? Mencoba oskill (pid) dari dalam utasnya sendiri, ia hanya menghentikan semua utas termasuk yang utama, harus dilakukan secara eksternal oleh orangtua, tetapi bagaimana cara mendapatkan pid anak itu dari orangtua?
Rodrigo Formighieri
Seperti orang lain telah mengisyaratkan, sayangnya ini tidak bekerja pada sesuatu seperti linux tertanam yang berjalan pada Arm 32 bit.
Travis Griggs
@ TravisGriggs Konsep ini portabel untuk Linux, termasuk platform ARM 32 bit. Anda hanya perlu mendapatkan nomor panggilan sistem yang benar, yang mungkin akan menjadi 224 pada ARM dan ARM64. Itu dapat ditentukan pada waktu membangun atau menjalankan dengan program C kecil. Ini bekerja untuk saya dengan Python 3.7 pada RPi. Jawaban Jake Tesler lebih baik jika Anda memiliki Python 3.8, yang belum ada dalam Raspbian 10.
TrentP
7

Saya melihat contoh ID utas seperti ini:

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

Dokumen threading juga mencantumkan nameatribut:

...

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

Anda bisa mendapatkan identitas utas berjalan saat ini. Ident dapat digunakan kembali untuk utas lainnya, jika utas saat ini berakhir.

Ketika Anda membuat instance dari Thread, sebuah nama diberikan secara implisit ke thread, yang merupakan pola: Thread-number

Nama tidak memiliki arti dan namanya tidak harus unik. Identitas semua utas yang berjalan unik.

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

Fungsi threading.current_thread () mengembalikan utas berjalan saat ini. Objek ini menampung seluruh informasi utas.

DeaD_EyE
sumber
0

Saya membuat banyak utas dengan Python, saya mencetak objek utas, dan saya mencetak id menggunakan identvariabel. Saya melihat semua id sama:

<Thread(Thread-1, stopped 140500807628544)>
<Thread(Thread-2, started 140500807628544)>
<Thread(Thread-3, started 140500807628544)>
shoaib shaikh
sumber
4
Saya kira itu didaur ulang, seperti yang identdikatakan dokumen : 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

Demikian pula untuk @brucexin, saya perlu mendapatkan pengenal utas OS-level (yang! = thread.get_ident()) Dan menggunakan sesuatu seperti di bawah ini untuk tidak bergantung pada angka-angka tertentu dan hanya 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)                                                                  

dan

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

...

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

ini tergantung pada Cython.

kirr
sumber
Saya berharap ini akan menjadi versi lintas platform yang saya cari, tetapi saya mendapatkan kesalahan tentang ini, invalid syntaxpointer setelah externkata kunci. Apakah ada sesuatu yang saya lewatkan. Apakah penting bahwa kode berada dalam modul terpisah dan memiliki ekstensi pyx? Atau apakah ini kompilasi ulang?
Travis Griggs
Ya, ini tergantung pada Cython dan harus berada dalam .pyxfile. Untuk "python murni" mungkin sesuatu yang serupa dapat dilakukan dengan ctypes juga.
kirr