2010-05-07 15 views
15

Tengo que esperar en un script hasta que se cumplan ciertas condiciones?¿Hay alguna manera fácil en Python de esperar hasta que cierta condición sea verdadera?

Sé que puedo rodar mis propios eventos usando variables de condición y amigos, pero no quiero tener problemas para implementarlo, ya que algunos cambios de propiedades de objetos provienen de un hilo externo en una biblioteca envuelta en C++ (Boost .Python), así que no puedo secuestrar __setattr__ en una clase y poner una variable de condición allí, lo que me deja tratando de crear y señalar una variable de condición Python desde C++, o envolver una nativa y esperarla en Python , ambos suenan inquietos, innecesariamente complicados y aburridos.

¿Existe alguna manera más fácil de hacerlo, salvo que se realice un sondeo continuo de la condición?

Lo ideal sería en la línea de

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

Respuesta

16

Por desgracia, la única posibilidad para satisfacer sus limitaciones es que periódicamente sondeo, por ejemplo ....:

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 

o similares. Esto se puede optimizar de varias formas si se descompone somepredicate (por ejemplo, si se sabe que es and de varias cláusulas, especialmente si algunas de las cláusulas están sujetas a la optimización por ser detectables a través de threading.Event so lo que sea, etc.) , pero en los términos generales que usted solicita, este enfoque ineficiente es la única salida.

+0

Eso es lo que terminé haciendo. Afortunadamente, el rendimiento no es un problema (es un script de prueba). –

+0

podría haber otra solución http://stackoverflow.com/a/7836454/995714 –

2

Has básicamente responde a su propia pregunta: no.

Dado que maneja bibliotecas externas en boost.python, que pueden cambiar objetos en su tiempo libre, necesita tener esas rutinas para llamar a una actualización del controlador de eventos o para trabajar con una condición.

0

Aquí es la extensión de roscado a la solución de 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) 
Cuestiones relacionadas