2010-05-07 16 views
15

Je dois attendre dans un script jusqu'à ce qu'un certain nombre de conditions deviennent vraies? Je sais que je peux lancer mon propre événement en utilisant des variables de condition et des amis, mais je ne veux pas passer par tous les soucis de l'implémenter, car certaines modifications de propriétés d'objets proviennent d'un thread externe dans une bibliothèque C++ encapsulée (Boost .Python), donc je ne peux pas simplement pirater __setattr__ dans une classe et y mettre une variable de condition, ce qui me laisse soit essayer de créer et signaler une variable de condition Python depuis C++, soit envelopper un natif et l'attendre en Python , qui semblent tous deux délicats, inutilement compliqués et ennuyeux.Y at-il un moyen facile en Python d'attendre jusqu'à ce que certaines conditions soient vraies?

Existe-t-il un moyen plus facile de le faire, sauf interrogation continue de la condition?

Idéalement, il serait le long des lignes de

res = wait_until(lambda: some_predicate, timeout) 
if (not res): 
    print 'timed out' 

Répondre

16

Malheureusement, la seule possibilité de répondre à vos contraintes est à périodiquement sondage, .... par exemple:

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 

ou similaires. Ceci peut être optimisé de plusieurs manières si somepredicate peut être décomposé (par exemple s'il est connu and de plusieurs clauses, particulièrement si certaines des clauses sont elles-mêmes sujettes à optimisation en étant détectables via threading.Event s ou autre, etc, etc.) , mais dans les termes généraux que vous demandez, cette approche inefficace est la seule issue.

+0

C'est ce que je fini par faire. Heureusement, la performance n'est pas un problème (c'est un script de test). –

+0

il pourrait y avoir une autre solution http://stackoverflow.com/a/7836454/995714 –

2

Vous avez essentiellement répondu à votre propre question: non. Puisque vous avez affaire à des bibliothèques externes dans boost.python, qui peuvent changer les objets à loisir, vous devez soit faire en sorte que ces routines appellent une actualisation du gestionnaire d'événements, soit travailler avec une condition.

0

Voici le extention de filetage à la solution d'Alex:

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) 
Questions connexes