Python threading interrupt sleep
Asked Answered
C

3

17

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

Casar answered 8/8, 2016 at 11:55 Comment(2)
You could implement an Event and use Event.wait(100)Akkadian
Loop through 100 time.sleep(1) and check for any exceptionsAnnorah
L
6

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().

Licensee answered 8/8, 2016 at 12:3 Comment(1)
According to https://mcmap.net/q/273885/-threading-condition-vs-threading-event an event maybe a better solution if we just want to interrupt sleep, but condition is better if we interrupt sleep to have exclusive access to some resource.Aftergrowth
S
35

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 .

Stockroom answered 10/3, 2017 at 5:11 Comment(1)
Additional info: you need only one Event if you want to unblock multiple threads at the same time. In my case, I have threads of a scanner back off when the target throws an error, but want to stop them gracefully when the user presses Ctrl+C. By having the threads all event.wait(timeout=backoff) as you suggested, I can call event.set() just once and unblock them all at the same time (after which the threads can read the "should_stop" boolean and exit gracefully, which I set to True before calling .set()). Thanks for the great answer, Shiming!Nitrile
L
6

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().

Licensee answered 8/8, 2016 at 12:3 Comment(1)
According to https://mcmap.net/q/273885/-threading-condition-vs-threading-event an event maybe a better solution if we just want to interrupt sleep, but condition is better if we interrupt sleep to have exclusive access to some resource.Aftergrowth
Y
1

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.

Yvonneyvonner answered 11/12, 2020 at 3:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.