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ść?
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ść?
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”).
Break? Jak to wpisać?
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.
Jeśli działa w powłoce Pythona, użyj Ctrl+ Z, w przeciwnym razie zlokalizuj pythonproces i zabij go.
^Z-> [1]+ Stopped -> kill %1aby zatrzymać zadanie nr 1 (lub zadanie% 1, jak to ujął bash)
fgprzywróci to od razu.
Ctrl+Znie 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 ...
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 :
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
ctrl + cnie kończy się, ale wyświetla KeyboardInterrupt.
To może pomóc.
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.