Python main thread interruption - python

Can anyone explain how the interrupt_main() method works in Python?
I've got this piece of Python code :
import time, thread
def f():
time.sleep(5)
thread.interrupt_main()
def g():
thread.start_new_thread(f, ())
time.sleep(10)
print time.time()
try:
g()
except KeyboardInterrupt:
print time.time()
And when I try to run it, it gives me the following output :
1380542215.5
# ... 10 seconds break...
1380542225.51
However, if I interrupt the program manually (CTRL-C), the thread is interrupted correctly :
1380542357.58
^C1380542361.49
Why does the thread interruption only occur after 10 seconds (and not 5) in the first example?
I found an ancient thread n Python mailing list, but it explains nearly nothing.

raise KeyboardInterrupt does not interrupt a time.sleep(). The former is handled entirely inside the python interpreter, the latter invokes an operating system function.
So, in your case, the keyboard interrupt was handled, but only when time.sleep() completed its system call.
Try this instead:
def g():
thread.start_new_thread(f, ())
for _ in range(10):
time.sleep(1)

Related

Python - How to break immediately out of loop without waiting for next iteration, or stop thread? [duplicate]

Is there a way in python to interrupt a thread when it's sleeping?
(As we can do in java)
I am looking for something like that.
import threading
from time import sleep
def f():
print('started')
try:
sleep(100)
print('finished')
except SleepInterruptedException:
print('interrupted')
t = threading.Thread(target=f)
t.start()
if input() == 'stop':
t.interrupt()
The thread is sleeping for 100 seconds and if I type 'stop', it interrupts
The correct approach is to use threading.Event. For example:
import threading
e = threading.Event()
e.wait(timeout=100) # instead of time.sleep(100)
In the other thread, you need to have access to e. You can interrupt the sleep by issuing:
e.set()
This will immediately interrupt the sleep. You can check the return value of e.wait to determine whether it's timed out or interrupted. For more information refer to the documentation: https://docs.python.org/3/library/threading.html#event-objects .
How about using condition objects: https://docs.python.org/2/library/threading.html#condition-objects
Instead of sleep() you use wait(timeout). To "interrupt" you call notify().
If you, for whatever reason, needed to use the time.sleep function and happened to expect the time.sleep function to throw an exception and you simply wanted to test what happened with large sleep values without having to wait for the whole timeout...
Firstly, sleeping threads are lightweight and there's no problem just letting them run in daemon mode with threading.Thread(target=f, daemon=True) (so that they exit when the program does). You can check the result of the thread without waiting for the whole execution with t.join(0.5).
But if you absolutely need to halt the execution of the function, you could use multiprocessing.Process, and call .terminate() on the spawned process. This does not give the process time to clean up (e.g. except and finally blocks aren't run), so use it with care.

Python : call a function and wait for its thread(s) to finish

I am using Python to script a gdb session. My goal is to run a function whenever a breakpoint is hit, using gdb.events.stop.connect.
Here is my code in essence, which I call from gdb by running source main.py :
RESULT = None
def breakpoint_handler(event):
global RESULT
RESULT = do_something(event) # boolean
sleep(1)
def main():
global RESULT
gdb.events.stop.connect(breakpoint_handler)
command = "some gdb command"
gdb.execute(command)
sleep(1)
if RESULT:
# do something
pass
else:
# something else
pass
main()
This code works, but only thanks to the sleep calls, that tries to make sure the gdb.execute(command)call actually finish executing the gdb command before continuing. There is only little documentation but my guess is that this function is threaded, which explains the effectiveness of the waitas a fix.
Is there a way to make this cleaner by waiting for the thread created by gdb.execute to finish processing, without having access to the body of this method ?
You can set an event inside your callback and wait for it in your main thread. Here is an example, with the callback being called after 5 seconds by timer:
import threading
def some_callback():
event.set()
event = threading.Event()
threading.Timer(5, some_callback).start()
event.wait()

Python: threads and KeyboardInterrupt

Given the following code (running under Linux)...
import threading
import time
def donothing(quit):
while True:
if quit.wait(1):
break
print 'quitting'
quit = threading.Event()
try:
t = threading.Thread(target=donothing, args=(quit,))
t.start()
t.join()
except KeyboardInterrupt:
print 'interrupt!'
quit.set()
Type ^C while the program is running will not generate a KeyboardInterrupt:
python example.py
^C^C^C^C^C^C^C^C^C
Adding a timeout of any value to t.join() changes this behavior. That is, if I have instead:
t.join(86400)
Then I see (without needing to wait 86400 seconds):
$ python example.py
^Cinterrupt!
quitting
What is going on here? I assume that in the first case the join operation locks the GIL and prevents any signal handlers from running, but why does adding any timeout change this behavior?
I've spent a little time poking through the code, and while I'm getting lost somewhere in Modules/_threadmodule.c it looks as if the same code path is followed regardless of whether or not a timeout was specified.

Python threading interrupt sleep

Is there a way in python to interrupt a thread when it's sleeping?
(As we can do in java)
I am looking for something like that.
import threading
from time import sleep
def f():
print('started')
try:
sleep(100)
print('finished')
except SleepInterruptedException:
print('interrupted')
t = threading.Thread(target=f)
t.start()
if input() == 'stop':
t.interrupt()
The thread is sleeping for 100 seconds and if I type 'stop', it interrupts
The correct approach is to use threading.Event. For example:
import threading
e = threading.Event()
e.wait(timeout=100) # instead of time.sleep(100)
In the other thread, you need to have access to e. You can interrupt the sleep by issuing:
e.set()
This will immediately interrupt the sleep. You can check the return value of e.wait to determine whether it's timed out or interrupted. For more information refer to the documentation: https://docs.python.org/3/library/threading.html#event-objects .
How about using condition objects: https://docs.python.org/2/library/threading.html#condition-objects
Instead of sleep() you use wait(timeout). To "interrupt" you call notify().
If you, for whatever reason, needed to use the time.sleep function and happened to expect the time.sleep function to throw an exception and you simply wanted to test what happened with large sleep values without having to wait for the whole timeout...
Firstly, sleeping threads are lightweight and there's no problem just letting them run in daemon mode with threading.Thread(target=f, daemon=True) (so that they exit when the program does). You can check the result of the thread without waiting for the whole execution with t.join(0.5).
But if you absolutely need to halt the execution of the function, you could use multiprocessing.Process, and call .terminate() on the spawned process. This does not give the process time to clean up (e.g. except and finally blocks aren't run), so use it with care.

Python thread holds up the rest of the script

Running Python 3.2 on Windows 7 Pro 64 Bit.
OK I have some very basic code here that's just not behaving like I want it to.
#!/usr/bin/env python
import time
import threading
def shutdown(sleeptime):
time.sleep(sleeptime)
print('I have executed')
threading.Thread(target = shutdown(5)).start()
print('I go first')
The idea being that the script runs, it starts a thread which sleeps for 5 seconds then prints out 'I have executed'. In the meantime the script keeps going and prints out 'I go first'.
What actually happens is that the script starts the thread, everything waits for it to finish and then it continues. Clearly I'm not doing the threading correctly but I'm having trouble finding simple examples of threading with Python 3.
Your statement:
threading.Thread(target = shutdown(5)).start()
can be equivalently written as:
x = shutdown(5)
threading.Thread(target = x).start()
I.e. you are calling shutdown first, then passing the result to the Thread constructor.
You need to pass your function, without calling it, and your argument list, to Thread separately:
threading.Thread(target = shutdown, args = (5,)).start()
Your target is not evaluating to a function, but rather the value of shutdown(5), which is None. You probably want it to be more like:
def shutdown(sleeptime):
def shutter_downer():
time.sleep(sleeptime)
print('I have executed')
return shutter_downer

Categories

Resources