web-dev-qa-db-fra.com

Python n'apparaît pas sur ps ou htop

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
27
Chamila

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
18
Nick Craig-Wood

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.

7
Grief

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
6
Oleg Golovanov

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