Python thread name doesn't show up on ps or htop

Question:

When I set the name for a Python thread, it doesn’t show up on htop or ps. The ps output only shows python as the thread name. Is there any way to set a thread name so that it shows up on system reports like them?

from threading import Thread
import time


def sleeper():
    while True:
        time.sleep(10)
        print "sleeping"

t = Thread(target=sleeper, name="Sleeper01")
t.start()
t.join()

ps -T -p {PID} output

  PID  SPID TTY          TIME CMD
31420 31420 pts/30   00:00:00 python
31420 31421 pts/30   00:00:00 python
Asked By: chamilad

||

Answers:

First install the prctl module. (On debian/ubuntu just type sudo apt-get install python-prctl)

from threading import Thread
import time
import prctl

def sleeper():
    prctl.set_name("sleeping tiger")
    while True:
        time.sleep(10)
        print "sleeping"

t = Thread(target=sleeper, name="Sleeper01")
t.start()
t.join()

This prints

$ ps -T
  PID  SPID TTY          TIME CMD
22684 22684 pts/29   00:00:00 bash
23302 23302 pts/29   00:00:00 python
23302 23303 pts/29   00:00:00 sleeping tiger
23304 23304 pts/29   00:00:00 ps

Note: python3 users may wish to use pyprctl.

Answered By: Nick Craig-Wood

On Python 2, I use the following monkey patch to propagate the Thread’s name to the system if prctl is installed in the system:

try:
    import prctl
    def set_thread_name(name): prctl.set_name(name)

    def _thread_name_hack(self):
        set_thread_name(self.name)
        threading.Thread.__bootstrap_original__(self)

    threading.Thread.__bootstrap_original__ = threading.Thread._Thread__bootstrap
    threading.Thread._Thread__bootstrap = _thread_name_hack
except ImportError:
    log('WARN: prctl module is not installed. You will not be able to see thread names')
    def set_thread_name(name): pass

After the execution of this code, you can set thread’s name as usual:

threading.Thread(target=some_target, name='Change monitor', ...)

That means, that if you already set names for threads, you don’t need to change anything. I cannot guarantee, that this is 100% safe, but it works for me.

Answered By: Grief

Prctl module is nice and provide many features, but depends libcap-dev package. Libcap2 is most likely installed because it is a dependency of many packages (systemd for example). So if you only need set thread name, use libcap2 over ctypes.

See improved Grief answer below.

LIB = 'libcap.so.2'
try:
    libcap = ctypes.CDLL(LIB)
except OSError:
    print(
        'Library {} not found. Unable to set thread name.'.format(LIB)
    )
else:
    def _name_hack(self):
        # PR_SET_NAME = 15
        libcap.prctl(15, self.name.encode())
        threading.Thread._bootstrap_original(self)

    threading.Thread._bootstrap_original = threading.Thread._bootstrap
    threading.Thread._bootstrap = _name_hack
Answered By: Oleg Golovanov

An alternative solution (actually a dirty one, since it sets the process name, not the thread name) is to use the setproctitle module from pypi.

You can install it with pip install setproctitle and use it as follow:

import setproctitle
import threading
import time

def a_loop():
    setproctitle.setproctitle(threading.currentThread().name)
    # you can otherwise explicitly declare the name:
    # setproctitle.setproctitle("A loop")
    while True:
        print("Looping")
        time.sleep(99)

t = threading.Thread(target=a_loop, name="ExampleLoopThread")
t.start()
Answered By: LanQuil

I was confused after I found a tool–py-spy to show python thread while running.

install: pip3 install -i https://pypi.doubanio.com/simple/ py-spy

usage: py-spy dump –pid process-number

for example, py-spy dump –pid 1234 can show all the thread stacks,name,id of python process 1234

Answered By: ryanlee

https://pypi.org/project/namedthreads/ provides a way to patch threading.Thread.start to call pthread_setname_np with the Python Thread.name.

It is compatible with Python 2.7 & 3.4+ (I’ve tested it with 3.10)

To activate it,

import namedthreads
namedthreads.patch()

Note that thread names in Python are unlimited, but pthreads has a limit of 15 char, so the Python name will be trimmed.

Answered By: John Vandenberg

I attempted to follow answers here to install python-prctl or pyprctl. However none of them could be installed because the need for a gcc that we don’t have.

After some digging on the net, this python issue 15500 gave a nice solution [https://bugs.python.org/issue15500]. Here is what I’ve got based on it:

import ctypes, os, threading
def set_thread_name_np(the_name):
    the_lib_path = "/lib/libpthread-2.42.so"
    if not os.path.isfile(the_lib_path):
        return None
    try:
        libpthread = ctypes.CDLL(the_lib_path)
    except:
        return None
    if hasattr(libpthread, "pthread_setname_np"):
        pthread_setname_np = libpthread.pthread_setname_np
        pthread_setname_np.argtypes = [ctypes.c_void_p,
                                       ctypes.c_char_p]
        pthread_setname_np.restype = ctypes.c_int
        if isinstance(the_name, str):
            the_name = the_name.encode('ascii', 'replace')
        if type(the_name) is not bytes:
            return None
        the_thread = threading.current_thread()
        ident = getattr(the_thread, "ident", None)
        if ident is not None:
            pthread_setname_np(ident, the_name[:15])
            return True
    return None
Answered By: minghua
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.