Existe um equivalente a CTRL + C no IPython Notebook no Firefox para quebrar células em execução?

100

Comecei a usar o Notebook IPython e estou gostando. Às vezes, escrevo um código com erros que exige muitos requisitos de memória ou tem um loop infinito. Acho a opção "interromper kernel" lenta ou não confiável e, às vezes, tenho que reiniciar o kernel, perdendo tudo na memória.

Às vezes também escrevo scripts que fazem com que o OS X fique sem memória e preciso fazer uma reinicialização forçada. Não tenho 100% de certeza, mas quando escrevo bugs como este antes e executo o Python no terminal, geralmente consigo CTRL+ Cmeus scripts.

Estou usando a distribuição Anaconda do notebook IPython com Firefox no Mac OS X.

wwwilliam
fonte
1
Nunca tive sucesso em interromper um loop infinito por meio do atalho cntrl + mi ou do kernel> interrupt dropdown no 0.13 (padrão para anaconda no MacOSX). O problema parece ter sido corrigido no 1.0.
KLDavenport

Respostas:

55

Posso estar errado, mas tenho quase certeza de que o botão "interromper kernel" apenas envia um sinal SIGINT para o código que você está executando no momento (essa ideia é apoiada pelo comentário de Fernando aqui ), que é a mesma coisa que bater CTRL + C serviria. Alguns processos em python lidam com SIGINTs mais abruptamente do que outros.

Se você precisa desesperadamente interromper algo que está sendo executado no iPython Notebook e iniciou o iPython Notebook de um terminal, pode pressionar CTRL + C duas vezes nesse terminal para interromper todo o servidor do iPython Notebook. Isso interromperá totalmente o iPython Notebook, o que significa que não será possível reiniciar ou salvar seu trabalho, então, obviamente, esta não é uma grande solução (você precisa pressionar CTRL + C duas vezes porque é um recurso de segurança para que as pessoas não fazê-lo por acidente). Em caso de emergência, no entanto, geralmente elimina o processo mais rapidamente do que o botão "interromper kernel".

Seaotternerd
fonte
13
Alternativamente, você pode reiniciar ou parar o kernel problemático - menos drástico do que matar o servidor ipython. Isso pode ser feito na Kernellista suspensa ou na página do servidor do notebook (o Shutdownbotão à direita do nome do notebook ofensivo).
drevicko
1
Infelizmente, parece que o navegador pode não responder tanto que é difícil acessar a página do servidor.
K.-Michael Aye
Existe uma maneira de interromper um processo em jupyter-console? II / control-c não funciona. E não há outro atalho para reiniciar o kernel.
alpha_989 de
75

Você pode pressionar Iduas vezes para interromper o kernel.

Isso só funciona se você estiver no modo de comando. Se ainda não estiver ativado, pressione Escpara ativá-lo.

fofinho
fonte
É para um intervalo de versão específico do IPython ou um sistema operacional específico?
Greg
6

Aqui estão os atalhos para o Notebook IPython.

Ctrl-m iinterrompe o kernel. (isto é, a única letra i depois Ctrl-m)

De acordo com essa resposta, Iduas vezes também funciona.

Skuli
fonte
5

Para adicionar ao acima: Se a interrupção não estiver funcionando, você pode reiniciar o kernel.

Vá para a lista suspensa do kernel >> reiniciar >> reiniciar e limpar a saída. Isso geralmente funciona. Se isso ainda não funcionar, elimine o kernel no terminal (ou gerenciador de tarefas) e reinicie.

Interromper não funciona bem para todos os processos. Eu tenho esse problema especialmente com o kernel R.

tomp
fonte
Este truque funcionou para mim: o Jupyter Notebook totalmente sem resposta devido ao agrupamento kmeans de vários núcleos de 2 bilhões de entradas (deveria saber antes)
Alex
3

ATUALIZAÇÃO : Transformei minha solução em um script python autônomo.

Essa solução me salvou mais de uma vez. Esperançosamente, outros o acharão útil. Este script python encontrará qualquer kernel jupyter usando mais do que cpu_thresholdCPU e solicita que o usuário envie um SIGINTpara o kernel (KeyboardInterrupt). Ele continuará sendo enviado SIGINTaté que o uso da CPU do kernel diminua cpu_threshold. Se houver vários kernels com comportamento incorreto, ele solicitará que o usuário interrompa cada um deles (ordenados do maior uso da CPU para o menor). Um grande agradecimento vai para gcbeltramini por escrever o código para encontrar o nome de um kernel jupyter usando a API jupyter. Este script foi testado em MACOS com python3 e requer jupyter notebook, requests, json e psutil.

Coloque o script em seu diretório inicial e o uso ficará assim:

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

Código de script abaixo:

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
fonte