- Остановка python с помощью ctrl + c
- Windows Python interpreter exits on Ctrl+C
- 1 Answer 1
- Ctrl-C doesn’t kill python on windows #100
- Comments
- SavageMessiah commented Apr 14, 2011
- minrk commented Apr 14, 2011
- SavageMessiah commented Apr 14, 2011
- minrk commented Apr 14, 2011
- minrk commented Apr 20, 2011
- bdejong commented May 23, 2011
- hintjens commented May 23, 2011
- minrk commented May 23, 2011
- zacharyvoase commented Jan 5, 2012
- minrk commented Jan 5, 2012
- zacharyvoase commented Jan 5, 2012
- harmv commented Jul 23, 2012
- minrk commented Jul 23, 2012
- schlamar commented Dec 20, 2012
- ckode commented Jan 24, 2013
- devdave commented Feb 19, 2013
- sscherfke commented Apr 25, 2013
- AndreLouisCaron commented May 27, 2014
- How do I capture SIGINT in Python?
- 12 Answers 12
- Yet Another Snippet
Остановка python с помощью ctrl + c
У меня есть python script, который использует потоки и делает много HTTP-запросов. Я думаю, что происходит, когда читается HTTP-запрос (используя urllib2), он блокирует и не отвечает на Ctrl C , чтобы остановить программу. Есть ли способ обойти это?
В Windows единственный верный способ – использовать Ctrl Break . Остановка каждого скрипта python мгновенно!
(Обратите внимание, что на некоторых клавиатурах “Разрыв” обозначается как “Пауза”.)
Нажатие Ctrl + c во время работы программы на Python приведет к тому, что python вызовет исключение KeyboardInterrupt . Вполне вероятно, что программа, которая делает много HTTP-запросов, будет иметь много кода обработки исключений. Если except части try – за except блока не определяет, какие исключения он должен поймать, он будет перехватывать все исключения, в том числе KeyboardInterrupt , что вы только что вызвали. Правильно закодированная программа Python будет использовать иерархию исключений Python и перехватывать только те исключения, которые получены из Exception .
Если вы не можете изменить код (или вам нужно убить программу, чтобы изменения вступили в силу), вы можете быстро нажать Ctrl + c . Первое из исключений KeyboardInterrupt выбьет вашу программу из блока try и, надеюсь, одно из более поздних исключений KeyboardInterrupt будет создано, когда программа находится за пределами блока try .
Если он запущен в оболочке Python, используйте Ctrl + Z , иначе найдите процесс python и убейте его.
Процесс прерывания зависит от оборудования и ОС. Таким образом, у вас будет совсем другое поведение в зависимости от того, где вы запускаете свой python script. Например, на машинах Windows мы имеем Ctrl + C ( SIGINT ) и Ctrl + Break ( SIGBREAK ).
Таким образом, хотя SIGINT присутствует во всех системах и может быть обработан и пойман, сигнал SIGBREAK является специфичным для Windows (и может быть отключен в CONFIG.SYS) и действительно обрабатывается BIOS как вектор прерывания INT 1Bh, поэтому этот ключ намного более мощный, чем любой другой. Поэтому, если вы используете какую-то ОС, отличную от * nix, вы получите разные результаты в зависимости от реализации, так как этого сигнала там нет, но другие. В Linux вы можете проверить, какие сигналы доступны вам:
Итак, если вы хотите поймать CTRL+BREAK signal в системе Linux, вам нужно будет проверить, что POSIX, они отобразили этот ключ. Популярные сопоставления:
Фактически, многие другие функции доступны в Linux, где ключ SysRq (системный запрос) может взять свою собственную жизнь…
Это сообщение устарело, но я недавно столкнулся с той же проблемой CTRL+C не заканчивая сценариями python на моем Linux . Я использовал CTRL + \ ( SIGQUIT ).
Ctrl + C Разница для Windows и Linux
Оказывается, что в Python 3.6 интерпретатор по-разному обрабатывает SIGINT, сгенерированный Ctrl + C, для Linux и Windows. В Linux ctrl + c будет работать в основном так, как и ожидалось, однако в Windows ctrl + c в основном не работает, если блокировка вызова, например, thread.join или ожидание ответа в Интернете (однако, он работает для time.sleep , однако). Здесь хорошее объяснение того, что происходит в интерпретаторе Python.
Решение 1. Используйте Ctrl + Break или Эквивалент
Используйте ниже сочетания клавиш в окне терминала/консоли, которые будут генерировать SIGBREAK на более низком уровне в ОС и завершать интерпретатор Python.
Mac OS и Linux
Ctrl + Shift +\or Ctrl + \
Windows:
- Общее: Ctrl+Break
- Dell: Ctrl+Fn+F6 или Ctrl+Fn+S
- Lenovo: Ctrl+Fn+F11 или Ctrl+Fn+B
- HP: Ctrl+Fn+Shift
- Samsung: Fn+Esc
Решение 2. Используйте Windows API
Ниже приведены удобные функции, которые обнаружат Windows и установят пользовательский обработчик для Ctrl + C в консоли:
Вы можете использовать выше, как это:
Решение 3: Метод опроса
Я не предпочитаю или рекомендую этот метод, потому что он излишне потребляет процессор и мощность, негативно влияющие на производительность.
для выхода из процесса python, подключенного к терминалу.
На mac/in Terminal:
- Показать инспектор (щелкните правой кнопкой мыши в окне терминала или “Шелл” > “Показать инспектор” )
- щелкните значок “Настройки” над “запущенными процессами”
- выберите из списка опций в разделе “Группа обработки сигналов” (Убейте, завершите, прерывайте и т.д.).
- Принуждение программы к закрытию с помощью Alt + F4 (выключает текущую программу)
- Спам кнопки X на CMD для ex
- Taskmanager (сначала Windows + R, а затем “taskmgr”), а затем завершает задачу.
Это может помочь.
Для справки, то, что убило процесс на моей Raspberry 3B+ (работает raspbian), было:
На моей французской клавиатуре AZERTY тач тоже номер 4.
Вы можете открыть свой диспетчер задач (ctrl + alt + delete, затем перейти к диспетчеру задач) и просмотреть его на python, и сервер называется (для примера) _go_app (соглашение об именах: _language_app).
Если я завершу задачу _go_app, то это завершит работу сервера, поэтому, зайдя туда в браузере, он скажет, что он “неожиданно завершился”, я также использую git bash, и когда я запускаю сервер, я не могу выйти из сервера в оболочке bash. с помощью ctrl + c или ctrl + pause, но как только вы завершите задачу python (та, которая использует 63.7 mb), она выйдет из серверного скрипта в bash и позволит мне использовать оболочку git bash.
ctrl + q мгновенно остановит текущий код и закроет все окна.
Windows Python interpreter exits on Ctrl+C
With most Python interpreters that I’ve used, Ctrl+C will cause the interpreter to print out » KeyboardInterrupt » and remain open. However, in a recent install on a new computer, Ctrl+C is causing the interpreter to exit, which is undesirable.
- Setting the signal.SIGINT handler still exits.
- There isn’t a startup script being run that could adjust behaviour.
- raise KeyboardInterrupt doesn’t exit the interpreter.
- No text is emitted on Ctrl+C. On Ctrl+Break, ^C is emitted before exit.
If I Ctrl+C during the snooze in the following snippet, the interpreter remains open.
Environment: Python 3.4.3 on Windows 10
1 Answer 1
Ctrl+C handling is broken at the shell prompt for Python versions prior to 3.6 when run on Windows 8 and above. It’s also broken for input and raw_input , for which you’ll get an EOFError instead of a KeyboardInterrupt . You can fix this by installing and enabling win_unicode_console — or by upgrading to 3.6
The problem is that Python’s old code for reading from the console depends on ReadFile setting the last error to ERROR_OPERATION_ABORTED (995) when reading is interrupted by Ctrl+C. In Windows 8, Microsoft completely rewrote how client processes talk to the console. In so doing they broke the documented contract for the behavior of ReadFile in this case. Without the error, Python thinks the aborted read was a successful read of 0 bytes. Normally this indicates end of file ( EOF ), so the REPL simply quits as if the user had typed Ctrl+Z, Enter.
ReadFile is a generic read from any File handle. There is also a specialized ReadConsole function. This one still behaves correctly, which is why win_unicode_console and 3.6+ don’t have this problem. They call ReadConsoleW to solve the separate problem of using the full range of Unicode in the console, and this just happens to also solve the Ctrl+C problem.
Ctrl-C doesn’t kill python on windows #100
Comments
SavageMessiah commented Apr 14, 2011
Like the title says — python 2.7, pyzmq and zeromq are both 2.1.4.
This simple code https://gist.github.com/920133 doesn’t die when you hit ctrl-c in the terminal.
The text was updated successfully, but these errors were encountered:
minrk commented Apr 14, 2011
Can you write a small C program and verify that behavior is different to libzmq itself?
If not, I can do it, but I don’t have convenient access to a Windows VM today.
SavageMessiah commented Apr 14, 2011
Tried it in c and ctrl-c worked fine.
minrk commented Apr 14, 2011
Okay, thanks. I’ll look into it once I have some access to Windows.
minrk commented Apr 20, 2011
I’ve done some exploring, and I’m not sure this isn’t a Python issue, rather than pyzmq.
I don’t know of a way to get reliable signal handling in extension code. ctrl-C definitely works fine on everything but Windows, and I’m not sure how the implementations differ.
bdejong commented May 23, 2011
I can definitely reproduce this (windows, . pyzmq 2.1.7) It’s rather annoying because (on windows) there is no way to stop processes using zmq except by killing them in the task manager.
hintjens commented May 23, 2011
Under win32 you may need to do some weird stuff to make Ctrl-C work. Here is how I used to do this in Xitami, ages ago:
minrk commented May 23, 2011
Thanks, I’ll see if I can’t figure it out with this.
The confusing thing is that ctrl-c does appear to work with a C program, but not a Python program.
zacharyvoase commented Jan 5, 2012
David Beazley’s talk on Python’s GIL explains very well why signal handling starts to fail the moment you call into C code, or use threads, or even carry out some Python operations that the interpreter considers atomic enough not to interrupt: http://www.dabeaz.com/python/GIL.pdf (see page 22 for the gory details).
This is definitely a Python issue.
minrk commented Jan 5, 2012
I am familiar with Beazley’s talk, but it does not seem to clarify why this is a Windows-specific issue. SIGINT works perfectly on posix. This issue requires both Python and Windows — posix+Python interrupts fine, as does Windows+C. But somehow on Windows Python prevents the event from interrupting the libzmq call.
zacharyvoase commented Jan 5, 2012
OK, I haven’t used Windows in several years so I can’t speak to this particular issue.
harmv commented Jul 23, 2012
I can confirm that this issue still exists.
This is a serious issue. This basically makes pyzmq un-workable on windows..
minrk commented Jul 23, 2012
If you are a Windows dev and know how to deal with the issue, a fix would be greatly appreciated. But I have neither the time nor relevant expertise to work it out, so it will not be fixed until someone steps up. There are also quite a few users who have been using pyzmq on Windows with this issue, so it is clearly not always made ‘un-workable’ by this, even if it is super annoying in certain cases.
schlamar commented Dec 20, 2012
I think this has something to do how Windows is handling I/O polling, because select has the same issue. This example reacts to a SIGINT just after the timeout has finished.
ckode commented Jan 24, 2013
Just an FYI to help you guys out. When ctrl+c doesn’t work on Windows, you can use ctrl+break. That will shut the process down without having to close cmd or using the Task Manager.
devdave commented Feb 19, 2013
Also, there’s always the scorched earth solution for blocking scripts in Win32 taskkill /F /IM python.exe That is going to kill ALL instances of python.exe for your account ( or global if admin ).
sscherfke commented Apr 25, 2013
@devdave I just heard that a killXYZ.bat seems to be quite a common thing on the Deskops of Windows developers. 😀
Nevertheless, I’d also like this bug to be fixed.
AndreLouisCaron commented May 27, 2014
I just stumbled on the this issue while integrating Tornado and PyZMQ. I know that CherryPy uses pywin32 to shut down cleanly on CTRL-C and CTRL-break events.
If you look at the documentation for SetConsoleCtrlHandler() , as suggested by @hintjens, you see:
Each console process has its own list of application-defined HandlerRoutine functions that handle CTRL+C and CTRL+BREAK signals. The handler functions also handle signals generated by the system when the user closes the console, logs off, or shuts down the system. Initially, the handler list for each process contains only a default handler function that calls the ExitProcess function. A console process adds or removes additional handler functions by calling the SetConsoleCtrlHandler function, which does not affect the list of handler functions for other processes.
My guess is that Python already adds its own console control handler to translate CTRL-C events into KeyboardInterrupt exceptions in the main thread. The problem is that this handler is asynchronous — it simply sets a flag to process when the interpreter runs next. However, since the interpreter is not running during a PyZMQ poll operation (the interpreter is blocked in a C function), this flag ends up never being checked.
There are two ways to check this:
- Use win32api.SetConsoleCtrlHandler() to register a console control handler that stops your poll operation and then returns 0, telling the system to continue executing handlers lower in the stack, inluding the Python handler that will raise the KeyboardInterrupt exception in the main thread.
- Give a timeout to the poll operation. In the worst case, you will wait until the poll operation completes before the KeyboardInterrupt exception is raised.
The touchy topic in the fix is that I’m not sure setting these handlers on each poll operation is desirable from a performance stand point (could be verified, but still). Ideally, the client program sets this only once at the start and stop of this program.
The other thing is that I’m not sure PyZMQ wants to introduce a dependency on pywin32.
If this is made optional (even on Windows), would you mind including it in the distribution?
Suppose I submit a pull request with the following:
- a new handle_console_events context manager that registers the console control handler;
- documentation explaining why, when, and how to use it;
- resolves to a simple warning about not being able to trap CTRL-C and CTRL-BREAK events when on Windows and pywin32 is not importable.
How do I capture SIGINT in Python?
I’m working on a python script that starts several processes and database connections. Every now and then I want to kill the script with a Ctrl + C signal, and I’d like to do some cleanup.
In Perl I’d do this:
How do I do the analogue of this in Python?
12 Answers 12
Register your handler with signal.signal like this:
Code adapted from here.
More documentation on signal can be found here.
‘); I’m not sure if KeyboardInterruptException is implemented as a SIGINT handler or if it really only catches Ctrl+C presses, but either way, using a signal handler makes your intent explicit (at least, if your intent is the same as OP’s). More importantly though, with a signal you don’t have to wrap try-catches around everything to make them work, which can be more or less of a composability and general software engineering win depending on the structure of your application. – Matt J Jun 20 ’11 at 7:55
You can treat it like an exception (KeyboardInterrupt), like any other. Make a new file and run it from your shell with the following contents to see what I mean:
And as a context manager:
You can handle CTRL + C by catching the KeyboardInterrupt exception. You can implement any clean-up code in the exception handler.
Yet Another Snippet
Referred main as the main function and exit_gracefully as the CTRL + c handler
I adapted the code from @udi to support multiple signals (nothing fancy) :
This code support the keyboard interrupt call ( SIGINT ) and the SIGTERM ( kill
In contrast to Matt J his answer, I use a simple object. This gives me the possibily to parse this handler to all the threads that needs to be stopped securlery.
If you want to ensure that your cleanup process finishes I would add on to Matt J’s answer by using a SIG_IGN so that further SIGINT are ignored which will prevent your cleanup from being interrupted.
You can use the functions in Python’s built-in signal module to set up signal handlers in python. Specifically the signal.signal(signalnum, handler) function is used to register the handler function for signal signalnum .
thanks for existing answers, but added signal.getsignal()
Personally, I couldn’t use try/except KeyboardInterrupt because I was using standard socket (IPC) mode which is blocking. So the SIGINT was cueued, but came only after receiving data on the socket.
Setting a signal handler behaves the same.
On the other hand, this only works for an actual terminal. Other starting environments might not accept Ctrl + C , or pre-handle the signal.
Also, there are «Exceptions» and «BaseExceptions» in Python, which differ in the sense that interpreter needs to exit cleanly itself, so some exceptions have a higher priority than others (Exceptions is derived from BaseException)