Gibt es eine Entsprechung zu STRG + C in IPython Notebook in Firefox, um laufende Zellen zu beschädigen?

98

Ich habe angefangen, das IPython Notebook zu verwenden und genieße es. Manchmal schreibe ich fehlerhaften Code, der einen enormen Speicherbedarf erfordert oder eine Endlosschleife hat. Ich finde die Option "Kernel unterbrechen" träge oder unzuverlässig, und manchmal muss ich den Kernel neu starten, wodurch alles im Speicher verloren geht.

Manchmal schreibe ich auch Skripte, die dazu führen, dass OS X nicht mehr über genügend Arbeitsspeicher verfügt, und ich muss einen harten Neustart durchführen. Ich bin nicht 100% sicher, aber wenn ich solche Fehler schon einmal geschrieben und Python im Terminal ausgeführt habe, kann ich normalerweise CTRL+ Cmeine Skripte.

Ich verwende die Anaconda-Distribution von IPython Notebook mit Firefox unter Mac OS X.

wwwilliam
quelle
1
Es war mir noch nie gelungen, eine Endlosschleife über die Verknüpfung cntrl + mi oder das Dropdown-Menü Kernel> Interrupt in 0.13 zu unterbrechen (Standard für Anaconda unter MacOSX). Das Problem scheint in 1.0 behoben zu sein.
KLDavenport

Antworten:

55

Ich könnte mich irren, aber ich bin mir ziemlich sicher, dass die Schaltfläche "Interrupt-Kernel" nur ein SIGINT-Signal an den Code sendet, den Sie gerade ausführen (diese Idee wird durch Fernandos Kommentar hier unterstützt ) STRG + C würde reichen. Einige Prozesse in Python verarbeiten SIGINTs abrupter als andere.

Wenn Sie dringend etwas stoppen müssen, das in iPython Notebook ausgeführt wird, und iPython Notebook von einem Terminal aus gestartet haben, können Sie in diesem Terminal zweimal STRG + C drücken, um den gesamten iPython Notebook-Server zu unterbrechen. Dadurch wird das iPython Notebook insgesamt gestoppt, was bedeutet, dass es nicht möglich ist, Ihre Arbeit neu zu starten oder zu speichern. Dies ist offensichtlich keine gute Lösung (Sie müssen STRG + C zweimal drücken, da dies eine Sicherheitsfunktion ist, damit die Benutzer dies nicht tun mach es aus Versehen). Im Notfall wird der Vorgang jedoch in der Regel schneller abgebrochen als mit der Schaltfläche "Kernel unterbrechen".

seaotternerd
quelle
13
Alternativ können Sie den fehlerhaften Kernel neu starten oder stoppen - weniger drastisch als das Beenden des ipython-Servers. Dies kann über die KernelDropdown-Liste oder über die Seite des Notebook-Servers erfolgen (die ShutdownSchaltfläche rechts neben dem Namen des betreffenden Notebooks).
Drevicko
1
Leider scheint der Browser so nicht mehr zu reagieren, dass es schwierig ist, die Serverseite zu erreichen.
K.-Michael Aye
Gibt es eine Möglichkeit, einen Prozess zu unterbrechen jupyter-console? II / control-c funktioniert nicht. Und es gibt keine andere Verknüpfung, um den Kernel neu zu starten.
Alpha_989
75

Sie können Izweimal drücken, um den Kernel zu unterbrechen.

Dies funktioniert nur, wenn Sie sich im Befehlsmodus befinden. Wenn noch nicht aktiviert, drücken Sie Esc, um es zu aktivieren.

Süße
quelle
Ist dies für einen bestimmten Versionsbereich von IPython oder ein bestimmtes Betriebssystem?
Greg
6

Hier finden Sie Verknüpfungen für das IPython-Notizbuch.

Ctrl-m iunterbricht den Kernel. (das heißt, der einzige Buchstabe i nach Ctrl-m)

Nach dieser Antwort Ifunktioniert auch zweimal.

Skuli
quelle
5

So fügen Sie Folgendes hinzu: Wenn der Interrupt nicht funktioniert, können Sie den Kernel neu starten.

Gehen Sie zur Kernel-Dropdown-Liste >> Neustart >> Neustart und löschen Sie die Ausgabe. Dies macht normalerweise den Trick. Wenn dies immer noch nicht funktioniert, beenden Sie den Kernel im Terminal (oder Task-Manager) und starten Sie ihn neu.

Interrupt funktioniert nicht bei allen Prozessen. Ich habe besonders dieses Problem mit dem R-Kernel.

tomp
quelle
Dieser Trick hat es für mich getan: völlig unempfindliches Jupyter-Notizbuch aufgrund der Clusterbildung von 2 Milliarden Einträgen mit mehreren Kernen (sollte vorher bekannt sein)
Alex
3

UPDATE : Verwandelte meine Lösung in ein eigenständiges Python-Skript.

Diese Lösung hat mich mehr als einmal gerettet. Hoffentlich finden es andere nützlich. Dieses Python-Skript findet jeden Jupyter-Kernel, der mehr als cpu_thresholdCPU verwendet, und fordert den Benutzer auf, einen SIGINTan den Kernel (KeyboardInterrupt) zu senden . Es wird so lange gesendet, SIGINTbis die CPU-Auslastung des Kernels nach unten geht cpu_threshold. Wenn es mehrere sich schlecht verhaltende Kernel gibt, wird der Benutzer aufgefordert, jeden von ihnen zu unterbrechen (geordnet nach der höchsten bis zur niedrigsten CPU-Auslastung). Ein großes Dankeschön geht an gcbeltramini für das Schreiben von Code, um den Namen eines Jupyter-Kernels mithilfe der Jupyter-API zu finden. Dieses Skript wurde unter MACOS mit Python3 getestet und erfordert Jupyter Notebook, Requests, JSON und Psutil.

Legen Sie das Skript in Ihr Home-Verzeichnis und die Verwendung sieht folgendermaßen aus:

python ~/interrupt_bad_kernels.py
Interrupt kernel chews cpu.ipynb; PID: 57588; CPU: 2.3%? (y/n) y

Skriptcode unten:

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()
mbecker
quelle