Czy istnieje odpowiednik CTRL + C w IPython Notatnik w przeglądarce Firefox w celu złamania uruchomionych komórek?

103

Zacząłem używać Notatnika IPython i sprawia mi to przyjemność. Czasami piszę błędny kod, który wymaga ogromnej ilości pamięci lub ma nieskończoną pętlę. Uważam, że opcja „przerwania jądra” jest powolna lub zawodna i czasami muszę ponownie uruchomić jądro, tracąc wszystko w pamięci.

Czasami piszę też skrypty, które powodują, że OS X zabraknie pamięci i muszę wykonać twardy restart. Nie jestem pewien w 100%, ale kiedy wcześniej pisałem takie błędy i uruchamiałem Pythona w terminalu, zwykle mogę CTRL+ Cmoje skrypty.

Używam dystrybucji Anaconda notebooka IPython z przeglądarką Firefox w systemie Mac OS X.

wwwilliam
źródło
1
Nigdy nie udało mi się przerwać nieskończonej pętli za pomocą skrótu cntrl + mi lub menu rozwijanego jądra> przerwań w 0.13 (domyślne dla anaconda na MacOSX). Wydaje się, że problem został rozwiązany w wersji 1.0.
KLDavenport

Odpowiedzi:

57

Mogę się mylić, ale jestem prawie pewien, że przycisk "przerwij jądro" po prostu wysyła sygnał SIGINT do kodu, który aktualnie uruchamiasz (ten pomysł jest wspierany przez komentarz Fernando tutaj ), co jest tym samym co uderzenie CTRL + C wystarczy. Niektóre procesy w Pythonie obsługują znaki SIGINT szybciej niż inne.

Jeśli desperacko potrzebujesz zatrzymać coś, co działa w iPython Notebook i uruchomiłeś iPython Notebook z terminala, możesz dwukrotnie nacisnąć CTRL + C na tym terminalu, aby przerwać działanie całego serwera iPython Notebook. Spowoduje to całkowite zatrzymanie iPython Notebook, co oznacza, że ​​nie będzie można ponownie uruchomić ani zapisać pracy, więc nie jest to oczywiście świetne rozwiązanie (musisz dwukrotnie nacisnąć CTRL + C, ponieważ jest to funkcja bezpieczeństwa, aby ludzie nie zrób to przypadkowo). Jednak w nagłych wypadkach zwykle zabija proces szybciej niż przycisk „przerwanie jądra”.

seaotternerd
źródło
13
Alternatywnie możesz zrestartować lub zatrzymać szkodliwe jądro - mniej drastyczne niż zabicie serwera ipython. Można to zrobić z Kernelmenu rozwijanego lub ze strony serwera notebooków ( Shutdownprzycisk po prawej stronie nazwy notatnika powodującego naruszenie).
drevicko
1
Niestety wygląda na to, że przeglądarka może przestać odpowiadać na tyle, że trudno jest dotrzeć do strony serwera.
K.-Michael Aye
Czy istnieje sposób na przerwanie procesu jupyter-console? II / control-c nie działa. I nie ma innego skrótu do ponownego uruchomienia jądra.
alpha_989
79

Możesz nacisnąć Idwa razy, aby przerwać działanie jądra.

Działa to tylko wtedy, gdy jesteś w trybie poleceń. Jeśli nie jest jeszcze włączony, naciśnij, Escaby go włączyć.

cutie
źródło
Czy to jest dla określonego zakresu wersji IPython czy konkretnego systemu operacyjnego?
Greg
Właśnie zaoszczędziłeś mi 20 minut, dziękuję nieznajomemu
sapo_cosmico
6

Oto skróty do Notatnika IPython.

Ctrl-m iprzerywa jądro. (czyli jedyna litera i po Ctrl-m)

Zgodnie z odpowiedzią Idziała również dwukrotnie.

Skuli
źródło
5

Aby dodać do powyższego: Jeśli przerwanie nie działa, możesz ponownie uruchomić jądro.

Przejdź do listy rozwijanej jądra >> restart >> restart i wyczyść wyjście. To zwykle załatwia sprawę. Jeśli to nadal nie działa, zabij jądro w terminalu (lub menedżerze zadań), a następnie uruchom ponownie.

Przerwanie nie działa dobrze dla wszystkich procesów. Szczególnie mam ten problem z jądrem R.

tomp
źródło
Ta sztuczka zrobiła to dla mnie: całkowicie nie reagujący notebook Jupyter z powodu wielordzeniowego klastra kmeans o 2 miliardach wpisów (powinien był wiedzieć wcześniej)
Alex
4

UPDATE : Przekształciłem moje rozwiązanie w samodzielny skrypt w języku Python.

To rozwiązanie nie raz mnie uratowało. Mam nadzieję, że inni uznają to za przydatne. Ten skrypt Pythona znajdzie jądro jupyter wykorzystujące więcej niż cpu_thresholdCPU i poprosi użytkownika o wysłanie SIGINTdo jądra (KeyboardInterrupt). Będzie wysyłał dalej, SIGINTdopóki użycie procesora jądra nie spadnie poniżej cpu_threshold. Jeśli istnieje wiele źle działających jąder, poprosi użytkownika o przerwanie każdego z nich (w kolejności od największego wykorzystania procesora do najniższego). Ogromne podziękowania dla gcbeltramini za napisanie kodu umożliwiającego znalezienie nazwy jądra jupyter za pomocą interfejsu jupyter api. Ten skrypt został przetestowany na MACOS z python3 i wymaga jupyter notebook, requests, json i psutil.

Umieść skrypt w swoim katalogu domowym, a użycie będzie wyglądało następująco:

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

Kod skryptu poniżej:

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
źródło