У мене є сценарій python, який використовує нитки та робить безліч HTTP-запитів. Я думаю, що відбувається в тому, що хоч HTTP-запит (за допомогою urllib2) читає, він блокує і не реагує CtrlCна зупинку програми. Чи є спосіб обходити це?
У мене є сценарій python, який використовує нитки та робить безліч HTTP-запитів. Я думаю, що відбувається в тому, що хоч HTTP-запит (за допомогою urllib2) читає, він блокує і не реагує CtrlCна зупинку програми. Чи є спосіб обходити це?
Відповіді:
У Windows єдиний вірний спосіб - це використання CtrlBreak. Зупиняє кожен сценарій python миттєво!
(Зверніть увагу, що на деяких клавіатурах "Перерва" позначений як "Пауза".)
Break? Як ввести його?
Натискання Ctrl+ cпід час запуску програми python призведе до того, що python створить KeyboardInterruptвиняток. Ймовірно, що програма, яка робить безліч запитів HTTP, матиме безліч код обробки винятків. Якщо exceptчастина try- exceptблок не визначає , які винятку він повинен зловити, він буде перехоплювати всі виключення , в тому числі , KeyboardInterruptщо ви тільки що викликали. Правильно кодована програма python буде використовувати ієрархію винятків python та вловлювати лише винятки, похідні від 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
Якщо ви не можете змінити код (або потрібно вбити програму, щоб зміни вступили в силу), ви можете спробувати натиснути Ctrl+ cшвидко. Перший з KeyboardInterruptвинятків виведе вашу програму з tryблоку, і, сподіваємось, одне з пізніших KeyboardInterruptвинятків буде піднято, коли програма знаходиться поза tryблоком.
Якщо він працює в оболонці Python, використовуйте Ctrl+ Z, інакше знайдіть pythonпроцес і вбийте його.
^Z-> [1]+ Stopped -> kill %1припинити роботу №1 (або роботу% 1, як
fgповерне це назад.
Ctrl+Zце не правильний спосіб зупинити скрипт пітона, і його слід уникати, якщо ви не плануєте відновити призупинений процес.
Процес переривання залежить від обладнання та ОС. Таким чином, у вас буде дуже різна поведінка залежно від того, де ви запускаєте свій скрипт python. Наприклад, на машинах Windows у нас є Ctrl+ C( SIGINT) і Ctrl+ Break(SIGBREAK ).
Отже, хоча SIGINT присутній у всіх системах і може оброблятися та перехоплюватися, сигнал SIGBREAK є специфічним для Windows (і його можна відключити в CONFIG.SYS ) і справді обробляє BIOS як вектор переривання INT 1Bh , саме тому ця клавіша набагато потужніший за будь-який інший. Тож якщо ви використовуєте деяку ОС * з ароматизованим * nix, ви отримаєте різні результати залежно від реалізації, оскільки цього сигналу немає, але інші є. У Linux ви можете перевірити, які сигнали доступні вам:
$ 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
Тож якщо ви хочете зафіксувати CTRL+BREAK сигнал у системі Linux, вам доведеться перевірити, на який POSIX-сигнал вони вказали цей ключ. Популярні карти:
CTRL+\ = SIGQUIT
CTRL+D = SIGQUIT
CTRL+C = SIGINT
CTRL+Z = SIGTSTOP
CTRL+BREAK = SIGKILL or SIGTERM or SIGSTOP
Насправді в Linux є багато інших функцій, де SysRqклавіша (System Request) може взяти на себе життя ...
Ctrl+ DРізниця для Windows та Linux
Виявляється, що з Python 3.6 інтерпретатор Python Ctrl+ по- Cрізному обробляє для Linux та Windows. Для Linux Ctrl+ Cпрацюватиме в основному так, як очікувалося, однак для Windows Ctrl+ C здебільшого не працює, особливо якщо Python виконує блокування викликів, таких як thread.joinабо очікування відповіді в Інтернеті. Це time.sleep, однак, працює. Ось приємне пояснення того, що відбувається в інтерпретаторі Python. Зауважте, що Ctrl+ Cгенерує SIGINT.
Рішення 1: Використовуйте Ctrl+ Breakабо еквівалент
Використовуйте нижче комбінації клавіш у вікні термінала / консолі, які будуть генеруватися SIGBREAKна нижчому рівні в ОС та припиняти інтерпретатор Python.
Mac OS та Linux
Ctrl+ Shift+ \або Ctrl+\
Windows :
Рішення 2: Використовуйте API API
Нижче представлені зручні функції, які виявлять Windows та встановлять користувальницький обробник для Ctrl+ Cу консолі:
#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)
Ви можете використовувати вище, як це:
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!
Рішення 3: Метод опитування
Я не віддаю перевагу або не рекомендую цей метод, оскільки він зайво споживає процесор і потужність, негативно впливаючи на продуктивність.
час імпорту нитки імпорту
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 + cне вимикається, а показує KeyboardInterrupt.
Вони можуть допомогти.
Ви можете відкрити свій диспетчер завдань (ctrl + alt + delete, потім перейти до диспетчера завдань) і подивитися через нього на python, а сервер викликається (наприклад) _go_app (умова іменування: _language_app).
Якщо я закінчу завдання _go_app, він закінчить сервер, тому, переходячи туди в браузері, він скаже це "несподівано закінчилося", я також використовую git bash, і коли я запускаю сервер, я не можу вирватися з сервера в оболонці bash з ctrl + c або ctrl + пауза, але як тільки ви закінчите завдання python (те, що використовує 63,7 mb), воно вирветься із серверного скрипту в bash і дозволить мені використовувати оболонку git bash. 
Для запису, те, що вбило процес на моєму Raspberry 3B + (запущений raspbian), було Ctrl+ '. На моїй французькій клавіатурі AZERTY натисканням 'є також номер 4.