Zatrzymywanie Pythona za pomocą ctrl + c

130

Mam skrypt w Pythonie, który używa wątków i wykonuje wiele żądań HTTP. Myślę, że podczas odczytu żądania HTTP (używającego urllib2) blokuje się i nie odpowiada, CtrlCaby zatrzymać program. Czy można to obejść?

jonatron
źródło
9
Nie wiem dlaczego, ale przynajmniej na OS X użycie Control + Backslash powoduje zakończenie działania i pojawia się okno dialogowe „awaria Pythona” ... dziwne. Niezbyt przydatne informacje, więc jest to komentarz!
micmoo
3
Właściwie to działa na wszystkich aplikacjach w Terminalu ...
micmoo
1
David Beazley opisał, w jaki sposób przerwanie Ctrl / C może zamienić wielowątkowy skrypt Pythona w procesora. Poruszono go tutaj ( stackoverflow.com/questions/990102/ ... ) z linkiem do przemówienia Beazleya.
Ned Deily

Odpowiedzi:

191

W systemie Windows jedynym pewnym sposobem jest użycie CtrlBreak. Natychmiast zatrzymuje każdy skrypt Pythona!

(Zwróć uwagę, że na niektórych klawiaturach „Przerwa” jest oznaczona jako „Wstrzymaj”).

Denis Masyukov
źródło
4
Co to jest Break? Jak to wpisać?
u0b34a0f6ae
6
Na klawiaturze powinien być przycisk
Pause_Break
18
A jeśli nie ma? Jestem na Intel Macbooku i nie ma on w pełni funkcjonalnej klawiatury.
Bluu
53
Na Linuksie należy użyć Ctrl-Shift- \
Michał Zieliński
12
ctrl + Z nie zabija skryptu, po prostu ukrywa go w tle i zawiesza. Możesz wpisać fg, aby go przywołać.
Shady Xu
87

Naciśnięcie Ctrl+ cpodczas działania programu w języku Python spowoduje zgłoszenie KeyboardInterruptwyjątku przez język Python . Jest prawdopodobne, że program, który wysyła wiele żądań HTTP, będzie miał dużo kodu obsługi wyjątków. Jeśli exceptczęść try- exceptbloku nie określa, które wyjątki powinna przechwytywać, przechwyci wszystkie wyjątki, w tym te KeyboardInterrupt, które właśnie spowodowałeś. Prawidłowo zakodowany program w języku Python będzie korzystał z hierarchii wyjątków języka Python i przechwytywał tylko wyjątki, z których pochodzą 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

Jeśli nie możesz zmienić kodu (lub musisz zabić program, aby zmiany odniosły skutek), możesz spróbować szybko nacisnąć Ctrl+ c. Pierwszy z KeyboardInterruptwyjątków wybije twój program z trybloku i miejmy nadzieję, że jeden z późniejszych KeyboardInterruptwyjątków zostanie zgłoszony, gdy program znajdzie się poza tryblokiem.

David Locke
źródło
1
To świetna odpowiedź, aby włączyć najpopularniejsze "przerwy", czyli ctrl + c.
Xerion
53

Jeśli działa w powłoce Pythona, użyj Ctrl+ Z, w przeciwnym razie zlokalizuj pythonproces i zabij go.

Andrew Hare
źródło
25
^Z-> [1]+ Stopped -> kill %1aby zatrzymać zadanie nr 1 (lub zadanie% 1, jak to ujął bash)
u0b34a0f6ae
23
Warto dodać do odpowiedzi, że Ctrl + Z po prostu wstrzymuje proces.
Matteo Italia
2
Aby rozwinąć powyższe: wstrzymanie procesu utrzymuje go w pamięci i powłoce, po prostu zapobiega używaniu zasobów procesora. Pliki, gniazda, wszystko jest nadal otwarte i używane. W rzeczywistości pisanie fgprzywróci to od razu.
RandomInsano,
2
Ctrl+Znie jest właściwym sposobem zatrzymania skryptu w Pythonie i należy go unikać, chyba że planujesz wznowić wstrzymany proces.
Josh Correia
33

Proces przerwania zależy od sprzętu i systemu operacyjnego. Będziesz więc miał bardzo różne zachowanie w zależności od tego, gdzie uruchomisz skrypt Pythona. Na przykład na komputerach z systemem Windows mamy Ctrl+ C( SIGINT) i Ctrl+ Break( SIGBREAK).

Tak więc, chociaż SIGINT jest obecny we wszystkich systemach i może być obsługiwany i przechwytywany, sygnał SIGBREAK jest specyficzny dla systemu Windows (i można go wyłączyć w CONFIG.SYS ) i jest naprawdę obsługiwany przez BIOS jako wektor przerwań INT 1Bh , dlatego ten klucz jest znacznie potężniejszy niż jakikolwiek inny. Więc jeśli używasz jakiegoś systemu operacyjnego o smaku * nix, otrzymasz różne wyniki w zależności od implementacji, ponieważ tego sygnału nie ma, ale inne są. W Linuksie możesz sprawdzić, jakie sygnały są dla Ciebie dostępne:

$ 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

Więc jeśli chcesz złapać CTRL+BREAK sygnał w systemie Linux, musisz sprawdzić, do jakiego sygnału POSIX zmapowali ten klucz. Popularne mapowania to:

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

W rzeczywistości wiele innych funkcji jest dostępnych w systemie Linux, w którym SysRqklawisz (Żądanie systemowe) może zacząć żyć własnym życiem ...

not2qubit
źródło
20

Ten post jest stary, ale ostatnio natknąłem się na ten sam problem Ctrl+ Cnie zamykania skryptów Pythona w systemie Linux. Użyłem Ctrl+ \( SIGQUIT).

Junius L.
źródło
Chociaż spowoduje to zrzut rdzenia, ale zatrzymał skrypt, dzięki
ospider,
17

Ctrl+ DRóżnica dla Windows i Linux

Okazuje się, że od Pythona 3.6 interpreter Pythona obsługuje Ctrl+ Cinaczej w systemach Linux i Windows. W systemie Linux Ctrl+ Cdziałałby głównie zgodnie z oczekiwaniami, jednak w systemie Windows Ctrl+ C przeważnie nie działa, zwłaszcza jeśli Python uruchamia połączenie blokujące, takie jak thread.joinlub oczekuje na odpowiedź sieciową. time.sleepJednak to działa . Oto przyjemne wyjaśnienie tego, co dzieje się w interprecie Pythona. Zwróć uwagę, że Ctrl+ Cgeneruje SIGINT.

Rozwiązanie 1: Użyj Ctrl+ Breaklub równoważnego

Użyj poniższych skrótów klawiaturowych w oknie terminala / konsoli, które wygenerują się SIGBREAKna niższym poziomie w systemie operacyjnym i zakończą działanie interpretera Pythona.

Mac OS i Linux

Ctrl+ Shift+ \lub Ctrl+\

Okna :

  • Ogólne: Ctrl+Break
  • Dell: Ctrl+ Fn+ F6lub Ctrl+ Fn+S
  • Lenovo: Ctrl+ Fn+ F11lub Ctrl+ Fn+B
  • HP: Ctrl+ Fn+Shift
  • Samsung: Fn+Esc

Rozwiązanie 2: Użyj interfejsu API systemu Windows

Poniżej znajdują się przydatne funkcje, które wykryją system Windows i zainstalują niestandardową obsługę dla Ctrl+ Cw konsoli:

#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)

Możesz użyć powyższego w ten sposób:

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!

Rozwiązanie 3: Metoda odpytywania

Nie preferuję ani nie polecam tej metody, ponieważ niepotrzebnie zużywa procesor i energię, negatywnie wpływając na wydajność.

import wątków czas importu

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
źródło
Nie, w Ubuntu, zarówno dla Pythona 2.7 i 3.6, naciśnięcie ctrl + cnie kończy się, ale wyświetla KeyboardInterrupt.
Rick
7

Na Macu naciśnij Ctrl+, \aby zakończyć proces Pythona podłączony do terminala.

Krunal
źródło
3

Na komputerze Mac / w terminalu:

  1. Pokaż inspektora (kliknij prawym przyciskiem myszy w oknie terminala lub Powłoka> Pokaż inspektora)
  2. kliknij ikonę Ustawienia nad „uruchomionymi procesami”
  3. wybierz z listy opcji w „Signal Process Group” (zabij, zakończ, przerwij itp.).
AG452
źródło
1
  • Wymuszanie zamknięcia programu za pomocą Alt + F4 (zamyka bieżący program)
  • Spamowanie przycisku X na CMD np
  • Taskmanager (najpierw Windows + R, a następnie „taskmgr”), a następnie zakończ zadanie.

To może pomóc.

Ciemna strona gier
źródło
1

Możesz otworzyć menedżera zadań (ctrl + alt + delete, a następnie przejść do menedżera zadań) i przejrzeć go w poszukiwaniu języka Python, a serwer nazywa się (na przykład) _go_app (konwencja nazewnictwa to: _language_app).

Jeśli zakończę zadanie _go_app to zakończy serwer, więc przechodząc tam w przeglądarce powie, że to „nieoczekiwanie zakończyło się”, używam też git bash, a kiedy uruchamiam serwer, nie mogę się wyrwać z serwera w powłoce basha z ctrl + c lub ctrl + pause, ale po zakończeniu zadania Pythona (tego używającego 63,7 MB) wyłamie się ze skryptu serwera w bash i pozwoli mi użyć powłoki git bash. wprowadź opis obrazu tutaj

JORDANO
źródło
1

Dla przypomnienia, tym, co zabiło proces na moim Raspberry 3B + (z systemem Raspbian) było Ctrl+ '. Na mojej francuskiej klawiaturze AZERTY dotyk 'jest również numerem 4.

Bertinchamps
źródło