En la práctica, un Timer es probablemente la forma más sencilla de hacer lo que desee.
Este código hará lo siguiente:
- Después de 1 segundo, se imprime "arg2 arg1"
- Después de 2 segundos, se imprime "búhos" BÚHOS BÚHOS
===
from threading import Timer
def twoArgs(arg1,arg2):
print arg1
print arg2
print ""
def nArgs(*args):
for each in args:
print each
#arguments:
#how long to wait (in seconds),
#what function to call,
#what gets passed in
r = Timer(1.0, twoArgs, ("arg1","arg2"))
s = Timer(2.0, nArgs, ("OWLS","OWLS","OWLS"))
r.start()
s.start()
===
El código anterior muy probablemente resolverá su problema.
¡Pero! Hay una manera alternativa, que no usa multihilo. Funciona mucho más como Javascript, que tiene un único subproceso.
Para esta versión de un solo hilo, todo lo que necesita hacer es almacenar la función y sus argumentos en un objeto, junto con la hora en que se debe ejecutar la función.
Una vez que tenga el objeto que contiene la llamada de función y el tiempo de espera, simplemente compruebe periódicamente si la función está lista para ejecutarse.
La forma correcta de hacer esto es haciendo un priority queue para almacenar todas las funciones que queremos ejecutar en el futuro, como se muestra en el siguiente código.
Al igual que en Javascript, este enfoque no garantiza que la función se ejecutará exactamente a tiempo. Una función que tarda mucho tiempo en ejecutarse retrasará las funciones posteriores. Pero sí garantiza que se ejecutará una función tan pronto como que su tiempo de espera.
Este código hará lo siguiente:
- Después de 1 segundo, se imprime "20"
- Después de 2 segundos, se imprime "132"
- Después de 3 segundos, se cierra.
===
from datetime import datetime, timedelta
import heapq
# just holds a function, its arguments, and when we want it to execute.
class TimeoutFunction:
def __init__(self, function, timeout, *args):
self.function = function
self.args = args
self.startTime = datetime.now() + timedelta(0,0,0,timeout)
def execute(self):
self.function(*self.args)
# A "todo" list for all the TimeoutFunctions we want to execute in the future
# They are sorted in the order they should be executed, thanks to heapq
class TodoList:
def __init__(self):
self.todo = []
def addToList(self, tFunction):
heapq.heappush(self.todo, (tFunction.startTime, tFunction))
def executeReadyFunctions(self):
if len(self.todo) > 0:
tFunction = heapq.heappop(self.todo)[1]
while tFunction and datetime.now() > tFunction.startTime:
#execute all the functions that are ready
tFunction.execute()
if len(self.todo) > 0:
tFunction = heapq.heappop(self.todo)[1]
else:
tFunction = None
if tFunction:
#this one's not ready yet, push it back on
heapq.heappush(self.todo, (tFunction.startTime, tFunction))
def singleArgFunction(x):
print str(x)
def multiArgFunction(x, y):
#Demonstration of passing multiple-argument functions
print str(x*y)
# Make some TimeoutFunction objects
# timeout is in milliseconds
a = TimeoutFunction(singleArgFunction, 1000, 20)
b = TimeoutFunction(multiArgFunction, 2000, *(11,12))
c = TimeoutFunction(quit, 3000, None)
todoList = TodoList()
todoList.addToList(a)
todoList.addToList(b)
todoList.addToList(c)
while True:
todoList.executeReadyFunctions()
===
En la práctica, es probable que hayan más en juego en ese bucle, mientras que sólo comprobar si sus funciones de tiempo de espera están listos para ir. Es posible que esté sondeando para la entrada del usuario, controle algún hardware, lea datos, etc.
Eso no es lo que 'setTimeout' hace en JavaScript. Lo que hace es poner en cola una función para su ejecución más tarde (es decir, una vez que expira el tiempo de espera). –
Sí ... Tienes razón. Pero solo quería dar la idea de lo que quería, no encontré la necesidad de ser completamente correcto desde el punto de vista técnico. – brunoais
Lo mejor que puedes hacer es simular algo con los hilos. –