Arrêter Python en utilisant Ctrl + C

128

J'ai un script python qui utilise des threads et fait beaucoup de requêtes HTTP. Je pense que ce qui se passe, c'est que pendant la lecture d'une requête HTTP (utilisant urllib2), elle bloque et ne répond pas CtrlCpour arrêter le programme. Y a-t-il un moyen de contourner cela?

Jonatron
la source
9
Je ne sais pas pourquoi, mais au moins sur OS X, l'utilisation de Control + Backslash le fait se terminer et vous obtenez une boîte de dialogue "python planté" ... étrange. Pas vraiment cette info utile, donc c'est un commentaire!
micmoo
3
En fait, cela fonctionne sur toutes les applications du terminal ...
micmoo
1
David Beazley a décrit comment une interruption Ctrl / C peut transformer un script Python multithread en un monopole du processeur. Il est abordé ici ( stackoverflow.com/questions/990102/… ) avec un lien vers le discours de Beazley.
Ned Deily le

Réponses:

189

Sous Windows, le seul moyen sûr est d'utiliser CtrlBreak. Arrête instantanément chaque script python!

(Notez que sur certains claviers, "Pause" est étiqueté comme "Pause".)

Denis Masyukov
la source
4
C'est quoi Break? Comment puis-je le saisir?
u0b34a0f6ae
5
Il devrait y avoir un bouton Pause_Break sur votre clavier
Jonatron
18
Et s'il n'y en a pas? Je suis sur un Macbook Intel et il n'a pas de clavier très complet.
Bluu
53
Sous Linux, vous devez utiliser Ctrl-Shift- \
Michał Zieliński
12
ctrl + Z ne tue pas le script, il le cache simplement en arrière-plan et le suspend. Vous pouvez taper fg pour le rappeler.
Shady Xu
84

Si vous appuyez sur Ctrl+ cpendant l'exécution d'un programme python, python lèvera une KeyboardInterruptexception. Il est probable qu'un programme qui fait beaucoup de requêtes HTTP aura beaucoup de code de gestion des exceptions. Si la exceptpartie du bloc try- exceptne spécifie pas les exceptions qu'elle doit intercepter, elle interceptera toutes les exceptions, y compris celles KeyboardInterruptque vous venez de provoquer. Un programme python correctement codé utilisera la hiérarchie des exceptions python et n'attrapera que les exceptions dérivées Exception.

#This is the wrong way to do things
try:
  #Some stuff might raise an IO exception
except:
  #Code that ignores errors

#This is the right way to do things
try:
  #Some stuff might raise an IO exception
except Exception:
  #This won't catch KeyboardInterrupt

Si vous ne pouvez pas changer le code (ou devez tuer le programme pour que vos modifications prennent effet), vous pouvez essayer d'appuyer sur Ctrl+ crapidement. La première des KeyboardInterruptexceptions éliminera votre programme du trybloc et, espérons-le, l'une des dernières KeyboardInterruptexceptions sera déclenchée lorsque le programme est en dehors d'un trybloc.

David Locke
la source
1
C'est une excellente réponse pour activer la "pause" la plus courante qui est ctrl + c.
Xerion
53

S'il s'exécute dans le shell Python, utilisez Ctrl+ Z, sinon localisez le pythonprocessus et tuez-le.

Andrew Hare
la source
25
^Z-> [1]+ Stopped -> kill %1pour arrêter le travail n ° 1 (ou le travail% 1 comme le dit bash)
u0b34a0f6ae
23
Cela vaut la peine d'ajouter à la réponse que Ctrl + Z met simplement le processus en pause .
Matteo Italia
2
Pour élaborer sur ce qui précède: la suspension du processus le maintient en mémoire et dans votre shell, cela l'empêche simplement d'utiliser les ressources du processeur. Fichiers, sockets, tout est toujours ouvert et utilisé. En fait, taper fgle ramènera tout de suite.
RandomInsano
2
Ctrl+Zn'est pas la bonne façon d'arrêter un script python et doit être évité à moins que vous ne prévoyiez de reprendre le processus en pause.
Josh Correia le
33

Le processus d'interruption dépend du matériel et du système d'exploitation. Vous aurez donc un comportement très différent selon l'endroit où vous exécutez votre script python. Par exemple, sur les machines Windows, nous avons Ctrl+ C( SIGINT) et Ctrl+ Break( SIGBREAK).

Ainsi, alors que SIGINT est présent sur tous les systèmes et peut être manipulé et capturé, le signal SIGBREAK est spécifique à Windows (et peut être désactivé dans CONFIG.SYS ) et est vraiment géré par le BIOS comme un vecteur d'interruption INT 1Bh , c'est pourquoi cette touche est beaucoup plus puissant que tout autre. Donc, si vous utilisez un système d'exploitation à saveur * nix, vous obtiendrez des résultats différents selon l'implémentation, puisque ce signal n'est pas présent, mais d'autres le sont. Sous Linux, vous pouvez vérifier quels signaux vous sont disponibles en:

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGEMT       8) SIGFPE       9) SIGKILL     10) SIGBUS
11) SIGSEGV     12) SIGSYS      13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGURG      17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGPWR      30) SIGUSR1
31) SIGUSR2     32) SIGRTMAX

Donc, si vous voulez capturer le CTRL+BREAK signal sur un système Linux, vous devrez vérifier à quel signal POSIX ils ont mappé cette clé. Les mappages populaires sont:

CTRL+\     = SIGQUIT 
CTRL+D     = SIGQUIT
CTRL+C     = SIGINT
CTRL+Z     = SIGTSTOP 
CTRL+BREAK = SIGKILL or SIGTERM or SIGSTOP

En fait, de nombreuses autres fonctions sont disponibles sous Linux, où la SysRqtouche (System Request) peut prendre une vie propre ...

not2qubit
la source
19

Ce post est ancien mais j'ai récemment rencontré le même problème de Ctrl+ Cne pas terminer les scripts Python sous Linux. J'ai utilisé Ctrl+ \( SIGQUIT).

Junius L.
la source
Bien que cela provoquera un vidage de
mémoire
17

Ctrl+ DDifférence pour Windows et Linux

Il s'avère qu'à partir de Python 3.6, l'interpréteur Python gère Ctrl+ Cdifféremment pour Linux et Windows. Pour Linux, Ctrl+ Cfonctionnerait essentiellement comme prévu mais sur Windows Ctrl+ la C plupart du temps ne fonctionne pas , surtout si Python est le blocage des appels en cours d' exécution tels que thread.joinou en attente de la réponse Web. Cela fonctionne pour time.sleep, cependant. Voici la belle explication de ce qui se passe dans l'interpréteur Python. Notez que Ctrl+ Cgénère SIGINT.

Solution 1: utiliser Ctrl+ Breakou équivalent

Utilisez ci-dessous les raccourcis clavier dans la fenêtre du terminal / console qui généreront SIGBREAKau niveau inférieur du système d'exploitation et mettront fin à l'interpréteur Python.

Mac OS et Linux

Ctrl+ Shift+ \ou Ctrl+\

Windows :

  • Général: Ctrl+Break
  • Dell: Ctrl+ Fn+ F6ou Ctrl+ Fn+S
  • Lenovo: Ctrl+ Fn+ F11ou Ctrl+ Fn+B
  • HP: Ctrl+ Fn+Shift
  • Samsung: Fn+Esc

Solution 2: utiliser l'API Windows

Vous trouverez ci-dessous des fonctions pratiques qui détecteront Windows et installeront le gestionnaire personnalisé pour Ctrl+ Cdans la console:

#win_ctrl_c.py

import sys

def handler(a,b=None):
    sys.exit(1)
def install_handler():
    if sys.platform == "win32":
        import win32api
        win32api.SetConsoleCtrlHandler(handler, True)

Vous pouvez utiliser ci-dessus comme ceci:

import threading
import time
import win_ctrl_c

# do something that will block
def work():
    time.sleep(10000)        
t = threading.Thread(target=work)
t.daemon = True
t.start()

#install handler
install_handler()

# now block
t.join()

#Ctrl+C works now!

Solution 3: méthode d'interrogation

Je ne préfère ni ne recommande cette méthode car elle consomme inutilement du processeur et de l'énergie, ce qui a un impact négatif sur les performances.

importation du temps d'importation des threads

def work():
    time.sleep(10000)        
t = threading.Thread(target=work)
t.daemon = True
t.start()
while(True):
    t.join(0.1) #100ms ~ typical human response
# you will get KeyboardIntrupt exception
Shital Shah
la source
Non, sur Ubuntu, pour Python 2.7 et 3.6, appuyer ctrl + cne quitte pas mais s'affiche KeyboardInterrupt.
Rick
7

Sur Mac, appuyez sur Ctrl+ \pour quitter un processus python attaché à un terminal.

Krunal
la source
3

Sur un Mac / dans Terminal:

  1. Afficher l'inspecteur (clic droit dans la fenêtre du terminal ou Shell> Afficher l'inspecteur)
  2. cliquez sur l'icône Paramètres au-dessus de "processus en cours"
  3. faites votre choix dans la liste des options sous "Groupe de traitement du signal" (Tuer, terminer, interrompre, etc.).
AG452
la source
1
  • Forcer le programme à se fermer en utilisant Alt + F4 (arrête le programme en cours)
  • Spamming le bouton X sur CMD par ex
  • Taskmanager (d'abord Windows + R, puis "taskmgr"), puis terminez la tâche.

Cela peut aider.

Le côté obscur du jeu
la source
1

Vous pouvez ouvrir votre gestionnaire de tâches (ctrl + alt + supprimer, puis aller dans le gestionnaire de tâches) et chercher python et le serveur est appelé (pour l'exemple) _go_app (la convention de dénomination est: _language_app).

Si je termine la tâche _go_app, cela mettra fin au serveur, donc aller là-bas dans le navigateur dira que cela s'est terminé de manière inattendue, j'utilise également git bash, et lorsque je démarre un serveur, je ne peux pas sortir du serveur dans le shell de bash avec ctrl + c ou ctrl + pause, mais une fois que vous avez terminé la tâche python (celle qui utilise 63,7 mb), elle sortira du script serveur dans bash et me permettra d'utiliser le shell git bash. entrez la description de l'image ici

JORDANO
la source
1

Pour mémoire, ce qui a tué le processus sur mon Raspberry 3B + (exécutant raspbian) était Ctrl+ '. Sur mon clavier français AZERTY, le toucher 'est également le numéro 4.

Bertinchamps
la source