Thanks,
Mike
try:
#code that reads input
except KeyboardInterrupt:
#Ctrl-C was pressed
Cheers,
Chris
--
http://blog.rebertia.com
You can use a try/except to catch a KeyboardInterrupt exception, or
you can trap it using the signal module:
http://docs.python.org/library/signal.html
You want to trap SIGINT.
HTH
Philip
Thanks to both of you. However, my question is also about whether I
need to be doing i/o or some similar operation for my program to
notice in any shape or form that Control-C has been pressed. In the
past, I've written Python programs that go about their business
ignoring Ctrl-C. Other programs respond to it immediately by exiting.
I think the difference is that the latter programs are doing i/o. But
I want to understand better what the "secret" is to responding to a
ctrl-C in any shape or form.
For example, does trapping SIGINT always work, regardless of what my
process is doing?
Thanks,
Mike
Hi Mike,
Sorry, I don't know the Python internals well enough to answer your
question.
Good luck
Philip
You don't need to be doing I/O in order to raise a KeyboardIneterrupt. For
example, the following program should use up a lot of your CPU until you
hit Ctrl-C.
>>> while True:
... pass
...
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
> In the past, I've written Python programs that go about their business
> ignoring Ctrl-C.
Can you be more specific? Can you share the relevant sections of these
programs? Were these programs multi-threaded?
> But I want to understand better what the "secret" is to responding to a
> ctrl-C in any shape or form.
Strictly speaking, I don't think you can always respond to a Ctrl-C in any
shape or form. Quoting from the signal module:
Although Python signal handlers are called asynchronously as far as the Python
user is concerned, they can only occur between the "atomic" instructions of the
Python interpreter. This means that signals arriving during long calculations
implemented purely in C (such as regular expression matches on large bodies of
text) may be delayed for an arbitrary amount of time.
HTH,
Ben
>PS> On Jul 6, 2009, at 5:37 PM, Michael Mossey wrote:
>>> What is required in a python program to make sure it catches a control-
>>> c on the command-line? Do some i/o? The OS here is Linux.
>PS> You can use a try/except to catch a KeyboardInterrupt exception, or you
>PS> can trap it using the signal module:
>PS> http://docs.python.org/library/signal.html
>PS> You want to trap SIGINT.
And make sure threads don't mess up the signal handling.
--
Piet van Oostrum <pi...@cs.uu.nl>
URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
Private email: pi...@vanoostrum.org
> On Jul 6, 2:47 pm, Philip Semanchuk <phi...@semanchuk.com> wrote:
>> On Jul 6, 2009, at 5:37 PM, Michael Mossey wrote:
>>
>> > What is required in a python program to make sure it catches a
>> > control-
>> > c on the command-line? Do some i/o? The OS here is Linux.
>>
>> You can use a try/except to catch a KeyboardInterrupt exception, or you
>> can trap it using the signal
>> module:http://docs.python.org/library/signal.html
>>
>> You want to trap SIGINT.
>>
>> HTH
>> Philip
>
> Thanks to both of you. However, my question is also about whether I need
> to be doing i/o or some similar operation for my program to notice in
> any shape or form that Control-C has been pressed. In the past, I've
> written Python programs that go about their business ignoring Ctrl-C.
I bet that somewhere in your code you have something like:
for x in really_big_list:
try:
long_running_process(x)
except:
continue
If that's what you're doing, stop! The correct way is:
for x in really_big_list:
try:
long_running_process(x)
except Exception:
# Let KeyboardInterrupt and SystemExit through.
continue
or even:
for x in really_big_list:
try:
long_running_process(x)
except (KeyboardInterrupt, SystemExit):
print "User requested exit... shutting down now"
cleanup()
raise
except Exception:
continue
--
Steven
Try some experiments. ;]
Note that it is a relatively recent change (in python 2.5) which made
KeyboardInterrupt not a child of Exception
ncw@dogger:~$ python2.4
Python 2.4.6 (#2, Feb 17 2009, 20:01:48)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Loaded customisations from '/home/ncw/.pystartup'
>>> isinstance(KeyboardInterrupt(), Exception)
True
>>>
ncw@dogger:~$ python2.5
Python 2.5.4 (r254:67916, Feb 17 2009, 20:16:45)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Loaded customisations from '/home/ncw/.pystartup'
>>> isinstance(KeyboardInterrupt(), Exception)
False
>>>
> for x in really_big_list:
> try:
> long_running_process(x)
> except (KeyboardInterrupt, SystemExit):
> print "User requested exit... shutting down now"
> cleanup()
> raise
> except Exception:
> continue
That is the backwards compatible way
--
Nick Craig-Wood <ni...@craig-wood.com> -- http://www.craig-wood.com/nick
Are you asking: "when would the python interpreter process
KeyboardInterrupt?"
In a multi threaded python program (where KeyboardInterrupt doesn't
always work), only the main thread can process KeyboardInterrupt; thus
the main thread must regain control before the interrupt is raised.
Normally, python will context switch (i.e. thread switch) every 100
interpreter "ticks", but when the interpreter received a SIGINT, the
interpreter will try to context switch as fast as it can (every tick) to
allow the main thread to regain control. So the answer is in
multithreaded python program: "when the main thread regains control"
In single threaded python program, the currently running thread is
always the main thread (which can handle KeyboardInterrupt). I believe
SIGINT is checked at every ticks. But SIGINT cannot interrupt atomic
operations (i.e. it cannot interrupt long operations that takes a single
tick).
An example, where python have difficulties processing KeyboardInterrupt:
>>> print 'foo'*10000000
...foofoofoo...
because printing a string is an atomic operation
I believe a tick in python is equivalent to a single bytecode, but
please correct me if I'm wrong.
> Michael Mossey wrote:
>> I want to understand better what the "secret" is to responding to a
>> ctrl-C in any shape or form.
>
> Are you asking: "when would the python interpreter process
> KeyboardInterrupt?"
> ...
> In single threaded python program, the currently running thread is
> always the main thread (which can handle KeyboardInterrupt). I believe
> SIGINT is checked at every ticks. But SIGINT cannot interrupt atomic
> operations (i.e. it cannot interrupt long operations that takes a
> single
> tick).
Some otherwise atomic single-bytecode operations (like large integer
arithmetic) do manual checks for whether signals were raised (though
that won't help at all if the operation isn't on the main thread).
> I believe a tick in python is equivalent to a single bytecode, but
> please correct me if I'm wrong.
Not all opcodes qualify as a tick. In general, those opcodes that
cause control to remain in the eval loop (and not make calls to other
Python or C functions) don't qualify as ticks (but there are
exceptions, e.g. so that while True: pass is interruptible). In
Python/ceval.c: PyEval_EvalFrameEx(), those opcodes that don't end in
goto fast_next_opcode are ticks.
Please correct me if _I'm_ wrong! :)
-Miles
You don't need to do I/O.
This works:
try:
process_forever()
except KeyboardInterrupt:
save critical stuff
write nice messages
I often wrap a large computational task like this, with the idea that
the exception can let me exit safely, in my case by writing restart
parameters and printing a summary pf progress to date.
Gerry