Когда я устанавливаю имя для потока Python, оно не отображается на htop или ps. Вывод ps показывает только python в качестве имени потока. Есть ли способ установить имя потока, чтобы оно отображалось в системных отчетах, как они?

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}

  PID  SPID TTY          TIME CMD
31420 31420 pts/30   00:00:00 python
31420 31421 pts/30   00:00:00 python
28
chamilad 18 Дек 2015 в 20:35

4 ответа

Лучший ответ

Сначала установите модуль prctl. (В Debian / Ubuntu просто введите 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()

Это печатает

$ 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
19
Nick Craig-Wood 18 Дек 2015 в 20:15

Я использую следующий патч обезьяны для распространения имени Python Thread в системе, если prctl установлен в системе:

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

После выполнения этого кода вы можете установить имя потока как обычно:

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

Это означает, что если вы уже задали имена для потоков, вам не нужно ничего менять. Я не могу гарантировать, что это на 100% безопасно, но это работает для меня.

7
Grief 8 Фев 2016 в 22:24

Альтернативное решение (на самом деле грязное, поскольку оно устанавливает имя процесса, а не имя потока) состоит в использовании модуля setproctitle из pypi.

Вы можете установить его с помощью pip install setproctitle и использовать его следующим образом:

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()
0
lanquil 24 Сен 2018 в 06:15

Модуль Prctl хорош и предоставляет много возможностей, но зависит от пакета libcap-dev. Libcap2, скорее всего, установлен, потому что он зависит от многих пакетов (например, systemd). Поэтому, если вам нужно только установить имя потока, используйте libcap2 поверх ctypes.

См. Улучшенный ответ Grief ниже.

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
7
Oleg Golovanov 3 Авг 2018 в 08:32