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ść?
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”).
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 thingstry:
#Some stuff might raise an IO exceptionexcept:
#Code that ignores errors#This is the right way to do thingstry:
#Some stuff might raise an IO exceptionexcept 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.
^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:
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+ Cprzeważ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:
import threading
import time
import win_ctrl_c
# do something that will blockdefwork():
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
defwork():
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
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.
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.
Odpowiedzi:
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”).
źródło
Break
? Jak to wpisać?Naciśnięcie Ctrl+ cpodczas działania programu w języku Python spowoduje zgłoszenie
KeyboardInterrupt
wyją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śliexcept
częśćtry
-except
bloku nie określa, które wyjątki powinna przechwytywać, przechwyci wszystkie wyjątki, w tym teKeyboardInterrupt
, 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
KeyboardInterrupt
wyjątków wybije twój program ztry
bloku i miejmy nadzieję, że jeden z późniejszychKeyboardInterrupt
wyjątków zostanie zgłoszony, gdy program znajdzie się pozatry
blokiem.źródło
Jeśli działa w powłoce Pythona, użyj Ctrl+ Z, w przeciwnym razie zlokalizuj
python
proces i zabij go.źródło
^Z
->[1]+ Stopped
->kill %1
aby zatrzymać zadanie nr 1 (lub zadanie% 1, jak to ujął bash)fg
przywróci to od razu.Ctrl+Z
nie jest właściwym sposobem zatrzymania skryptu w Pythonie i należy go unikać, chyba że planujesz wznowić wstrzymany proces.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 ...
źródło
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
).źródło
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.join
lub oczekuje na odpowiedź sieciową.time.sleep
Jednak to działa . Oto przyjemne wyjaśnienie tego, co dzieje się w interprecie Pythona. Zwróć uwagę, że Ctrl+ CgenerujeSIGINT
.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ę
SIGBREAK
na niższym poziomie w systemie operacyjnym i zakończą działanie interpretera Pythona.Mac OS i Linux
Ctrl+ Shift+ \lub Ctrl+\
Okna :
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
źródło
ctrl + c
nie kończy się, ale wyświetlaKeyboardInterrupt
.Na Macu naciśnij Ctrl+, \aby zakończyć proces Pythona podłączony do terminala.
źródło
Na komputerze Mac / w terminalu:
źródło
To może pomóc.
źródło
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.
źródło
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.
źródło