使用事件循环(而非线程)在延迟后执行函数或在给定秒数内重复执行函数,可以采取以下方法:
Tkinter
from Tkinter import Tk
def foo():
print("timer went off!")
def countdown(n, bps, root):
if n == 0:
root.destroy()
else:
print(n)
root.after(1000 / bps, countdown, n - 1, bps, root)
root = Tk()
root.withdraw()
root.after(4000, foo)
root.after(0, countdown, 10, 2, root)
root.mainloop()
print("done")
输出
10
9
8
7
6
5
4
3
timer went off!
2
1
done
Gtk
from gi.repository import GObject, Gtk
def foo():
print("timer went off!")
def countdown(n):
if n[0] == 0:
Gtk.main_quit()
else:
print(n[0])
n[0] -= 1
return True
GObject.timeout_add(4000, foo)
GObject.timeout_add(500, countdown, [10])
Gtk.main()
print("done")
输出
10
9
8
7
6
5
4
timer went off!
3
2
1
done
Twisted
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
def foo():
print("timer went off!")
def countdown(n):
if n[0] == 0:
reactor.stop()
else:
print(n[0])
n[0] -= 1
reactor.callLater(4, foo)
LoopingCall(countdown, [10]).start(.5)
reactor.run()
print("done")
输出
10
9
8
7
6
5
4
3
timer went off!
2
1
done
异步编程库Asyncio
Python 3.4引入了新的临时API,用于异步IO -asyncio
模块:
import asyncio
def foo():
print("timer went off!")
def countdown(n):
if n[0] == 0:
loop.stop()
else:
print(n[0])
n[0] -= 1
def frange(start=0, stop=None, step=1):
while stop is None or start < stop:
yield start
start += step
def call_every(loop, seconds, func, *args, now=True):
def repeat(now=True, times=frange(loop.time() + seconds, None, seconds)):
if now:
func(*args)
loop.call_at(next(times), repeat)
repeat(now=now)
loop = asyncio.get_event_loop()
loop.call_later(4, foo)
call_every(loop, 0.5, countdown, [10])
loop.run_forever()
loop.close()
print("done")
输出
10
9
8
7
6
5
4
3
timer went off!
2
1
done
注意:这些方法之间的界面和行为存在细微差别。