PythonでスレッドIDを見つける方法


178

マルチスレッドのPythonプログラムとwriteLog(message)、タイムスタンプとそれに続くメッセージを出力するユーティリティ関数があります。残念ながら、結果のログファイルでは、どのスレッドがどのメッセージを生成しているかはわかりません。

writeLog()メッセージに何かを追加して、どのスレッドがそれを呼び出しているかを識別できるようにしたいと思います。明らかに、スレッドにこの情報を渡すだけでもかまいませんが、それははるかに多くの作業になります。os.getpid()使用できるスレッドと同等のスレッドはありますか?

回答:


226

threading.get_ident()動作する、またはthreading.current_thread().ident(またはthreading.currentThread().identPython <2.6の場合)。


3
ニコラスのリンクを修正しました。最近、ドキュメントのタイトルにカーソルを合わせると、右側に小さな赤い記号が表示されることに気付きました。ドキュメントへのより具体的なリンクについては、コピーして貼り付けてください:-)
Jon Cage

2
Jythonを使用している場合threading.currentThread()は、バージョン2.5以降(camel_caseではなく、camelCase)が必要です。
Cam Jackson

3
@CharlesAndersonに注意してください。Thread.nameのPythonドキュメントには、「name-識別目的でのみ使用される文字列。セマンティクスはありません。複数のスレッドに同じ名前を付けることができます。初期名はコンストラクターによって設定されます。」
drevicko

7
また、少なくともOS XのPython 2.5および2.6では、threading.current_thread().ident不適切なバグがあるようNoneです。おそらく、ちょうど使用に意味があるthread.get_ident()のPython 2とthreading.current_thread().identPythonの3中
ニコラス・ライリー

5
私の答えの以前のバージョンではなかった言及をthread.get_ident()threading.get_ident()-ドキュメントへのリンクをたどるのPython 3.3で追加されました)。
ニコラスライリー

67

ロギングモジュールを使用すると、現在のスレッド識別子を各ログエントリに自動的に追加できます。ロガー形式の文字列でこれらのLogRecordマッピングキーの1つを使用するだけです。

%(thread)d: スレッドID(利用可能な場合)。

%(threadName)s: スレッド名(利用可能な場合)。

それを使ってデフォルトのハンドラを設定します。

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

ロガーを使用しています。だからあなたの答えは最も簡単な解決策だと思います。しかし、私は<concurrent.futures.thread.ThreadPoolExecutor object at 0x7f00f882a438>_2 これをスレッド名として取得しています。その2つは呼び出した私のスレッド番号ですか
Ravi Shanker Reddy

22

thread.get_ident()Linuxでは、この関数は長整数を返します。実際にはスレッドIDではありません。

このメソッドを使用し、Linuxで実際にスレッドIDを取得します。

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)

これは時々使用できますが、移植性はありません
Piyush Kansal

3
この回答を編集して、リンクが悪くなった場合でも訪問者に役立つようにしてください。
josliber

スレッドを起動するたびに自分のself.pidをpidで満たすことができるように、スレッドクラスのstart()メソッドをラップする方法 独自のスレッド内からos.kill(pid)を試しましたが、メインを含むすべてのスレッドを停止するだけで、親が外部で行う必要がありますが、親からその子pidを取得する方法は?
Rodrigo Formighieri

他の人がほのめかしたように、これは悲しいことに32ビットArmで実行されている組み込みLinuxのようなものでは機能しません。
Travis Griggs

@TravisGriggsこの概念は、32ビットARMプラットフォームを含むLinuxに移植可能です。正しいシステムコール番号を取得する必要があるだけです。これは、おそらくARMおよびARM64では224になります。小さなCプログラムを使用して、ビルド時または実行時に決定できます。これは、RPiでPython 3.7を使用する場合に機能します。Jake Teslerの答えは、Raspbian 10にはまだ存在しないPython 3.8を持っている場合に適しています。
TrentP


7

私はこのようなスレッドIDの例を見ました:

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

threadingモジュールのドキュメントのリストはname、同様の属性:

...

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

現在実行中のスレッドのIDを取得できます。現在のスレッドが終了した場合、IDは他のスレッドで再利用できます。

スレッドのインスタンスを作成すると、次のパターンである名前がスレッドに暗黙的に与えられます。スレッド番号

名前は意味がなく、名前は一意である必要はありません。実行中のすべてのスレッドのIDは一意です。

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

関数threading.current_thread()は、現在実行中のスレッドを返します。このオブジェクトは、スレッドの情報全体を保持します。


0

Pythonで複数のスレッドを作成し、スレッドオブジェクトを出力し、ident変数を使用してIDを出力しました。すべてのIDが同じであることがわかります。

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

4
私はそれがリサイクルされていると思います、例えばドキュメント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

同様に、私は(!= OSレベルのスレッドの識別子を取得するために必要な@brucexinにthread.get_ident()特定の数に依存し、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)                                                                  

そして

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

...

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

これはCythonに依存します。


これが私が探していたクロスプラットフォームのバージョンになると期待していましたが、これについてエラーが発生しました。キーワードのinvalid syntax後にポインタがありますextern。何か足りないものはありますか?コードが別のモジュールにあり、pyx拡張子を持つことが重要ですか?それともこれは(再)コンパイルのものですか?
Travis Griggs

はい、これはCythonに依存し、.pyxファイルに存在する必要があります。「純粋なpython」の場合、ctypesでも同様のことが可能です。
kirr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.