Lorsque je définit le nom d'un thread Python, il n'apparaît pas sur htop ou ps. La sortie ps affiche uniquement python
comme nom de thread. Y a-t-il un moyen définir un nom de thread afin qu'il apparaisse sur les rapports système comme eux?
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()
sortie 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
Installez d'abord le module prctl . (Sur debian/ubuntu, tapez simplement 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()
Ceci imprime
$ 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
J'utilise le patch de singe suivant pour propager python Nom du thread sur le système si prctl
est installé dans le système:
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
Après l'exécution de ce code, vous pouvez définir le nom du thread comme d'habitude:
threading.Thread(target=some_target, name='Change monitor', ...)
Cela signifie que si vous définissez déjà des noms pour les threads, vous n'avez rien à changer. Je ne peux pas garantir que c'est 100% sûr, mais cela fonctionne pour moi.
Le module Prctl est agréable et offre de nombreuses fonctionnalités, mais dépend du paquet libcap-dev. Libcap2 est très probablement installé car il s'agit d'une dépendance de nombreux packages (systemd par exemple). Donc, si vous n'avez besoin que de définir le nom du thread, utilisez libcap2 sur les ctypes.
Voir la réponse améliorée au chagrin ci-dessous.
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
Une solution alternative (en fait une sale, car elle définit le nom du processus, pas le nom du thread) consiste à utiliser le module setproctitle
de pypi.
Vous pouvez l'installer avec pip install setproctitle
et utilisez-le comme suit:
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()