ACTUALIZACIÓN : Convertí mi solución en un script de Python independiente.
Esta solución me ha salvado más de una vez. Ojalá otros lo encuentren útil. Esta secuencia de comandos de Python encontrará cualquier kernel de jupyter que utilice más de la cpu_threshold
CPU y le pide al usuario que envíe un SIGINT
al kernel (KeyboardInterrupt). Seguirá enviando SIGINT
hasta que el uso de la CPU del kernel sea inferior cpu_threshold
. Si hay varios núcleos que se comportan mal, se le pedirá al usuario que interrumpa cada uno de ellos (ordenados por el uso de CPU más alto al más bajo). Un gran agradecimiento a gcbeltramini por escribir código para encontrar el nombre de un kernel de jupyter usando la api de jupyter. Este script se probó en MACOS con python3 y requiere un cuaderno jupyter, solicitudes, json y psutil.
Coloque el script en su directorio de inicio y luego el uso se ve así:
python ~/interrupt_bad_kernels.py
Interrupt kernel chews cpu.ipynb; PID: 57588; CPU: 2.3%? (y/n) y
Código de secuencia de comandos a continuación:
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()