METTRE À JOUR : J'ai transformé ma solution en un script python autonome.
Cette solution m'a sauvé plus d'une fois. J'espère que d'autres le trouveront utile. Ce script python trouvera n'importe quel noyau jupyter utilisant plus que le cpu_threshold
processeur et invite l'utilisateur à envoyer un SIGINT
au noyau (KeyboardInterrupt). Il continuera à envoyer SIGINT
jusqu'à ce que l'utilisation du processeur par le noyau soit inférieure cpu_threshold
. S'il y a plusieurs noyaux qui se comportent mal, cela demandera à l'utilisateur d'interrompre chacun d'eux (triés par l'utilisation du processeur la plus élevée au plus bas). Un grand merci à gcbeltramini pour avoir écrit du code pour trouver le nom d'un noyau jupyter en utilisant l'API jupyter. Ce script a été testé sur MACOS avec python3 et nécessite jupyter notebook, requests, json et psutil.
Mettez le script dans votre répertoire personnel et son utilisation ressemble à ceci:
python ~/interrupt_bad_kernels.py
Interrupt kernel chews cpu.ipynb; PID: 57588; CPU: 2.3%? (y/n) y
Code de script ci-dessous:
from os import getpid, kill
from time import sleep
import re
import signal
from notebook.notebookapp import list_running_servers
from requests import get
from requests.compat import urljoin
import ipykernel
import json
import psutil
def get_active_kernels(cpu_threshold):
"""Get a list of active jupyter kernels."""
active_kernels = []
pids = psutil.pids()
my_pid = getpid()
for pid in pids:
if pid == my_pid:
continue
try:
p = psutil.Process(pid)
cmd = p.cmdline()
for arg in cmd:
if arg.count('ipykernel'):
cpu = p.cpu_percent(interval=0.1)
if cpu > cpu_threshold:
active_kernels.append((cpu, pid, cmd))
except psutil.AccessDenied:
continue
return active_kernels
def interrupt_bad_notebooks(cpu_threshold=0.2):
"""Interrupt active jupyter kernels. Prompts the user for each kernel."""
active_kernels = sorted(get_active_kernels(cpu_threshold), reverse=True)
servers = list_running_servers()
for ss in servers:
response = get(urljoin(ss['url'].replace('localhost', '127.0.0.1'), 'api/sessions'),
params={'token': ss.get('token', '')})
for nn in json.loads(response.text):
for kernel in active_kernels:
for arg in kernel[-1]:
if arg.count(nn['kernel']['id']):
pid = kernel[1]
cpu = kernel[0]
interrupt = input(
'Interrupt kernel {}; PID: {}; CPU: {}%? (y/n) '.format(nn['notebook']['path'], pid, cpu))
if interrupt.lower() == 'y':
p = psutil.Process(pid)
while p.cpu_percent(interval=0.1) > cpu_threshold:
kill(pid, signal.SIGINT)
sleep(0.5)
if __name__ == '__main__':
interrupt_bad_notebooks()