The Python Oracle

Is there an easy way in Python to wait until certain condition is true?

This video explains
Is there an easy way in Python to wait until certain condition is true?

--

Become part of the top 3% of the developers by applying to Toptal
https://topt.al/25cXVn

--

Track title: CC M Beethoven - Piano Sonata No 3 in C 3

--

Chapters
00:00 Question
01:07 Accepted answer (Score 50)
01:53 Answer 2 (Score 16)
02:46 Answer 3 (Score 7)
04:58 Answer 4 (Score 3)
05:32 Thank you

--

Full question
https://stackoverflow.com/questions/2785...

Answer 1 links:
[https://pypi.org/project/waiting/]: https://pypi.org/project/waiting/

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ACCEPTED ANSWER

Score 53


Unfortunately the only possibility to meet your constraints is to periodically poll, e.g....:

import time

def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
  mustend = time.time() + timeout
  while time.time() < mustend:
    if somepredicate(*args, **kwargs): return True
    time.sleep(period)
  return False

or the like. This can be optimized in several ways if somepredicate can be decomposed (e.g. if it's known to be an and of several clauses, especially if some of the clauses are in turn subject to optimization by being detectable via threading.Events or whatever, etc, etc), but in the general terms you ask for, this inefficient approach is the only way out.




ANSWER 2

Score 21


Another nice package is waiting - https://pypi.org/project/waiting/

install:

pip install waiting

Usage: You pass a function that will be called every time as a condition, a timeout, and (this is useful) you can pass a description for the waiting, which will be displayed if you get TimeoutError.

using function:

from waiting import wait


def is_something_ready(something):
    if something.ready():
        return True
    return False


# wait for something to be ready
something = # whatever

wait(lambda: is_something_ready(something), timeout_seconds=120, waiting_for="something to be ready")

# this code will only execute after "something" is ready
print("Done")

Note: the function must return a boolean - True when the wait is over, False otherwise




ANSWER 3

Score 4


Here is the threading extention to Alex's solution:

import time
import threading

# based on https://stackoverflow.com/a/2785908/1056345                                                                                                                                                                                                                                                                         
def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
    must_end = time.time() + timeout
    while time.time() < must_end:
        if somepredicate(*args, **kwargs):
            return True
        time.sleep(period)
    return False

def wait_until_par(*args, **kwargs):
    t = threading.Thread(target=wait_until, args=args, kwargs=kwargs)
    t.start()
    print ('wait_until_par exits, thread runs in background')

def test():
    print('test')

wait_until_par(test, 5)



ANSWER 4

Score 3


You've basically answered your own question: no.

Since you're dealing with external libraries in boost.python, which may change objects at their leisure, you need to either have those routines call an event handler refresh, or work with a condition.