Python Timer 用法與範例

本篇 ShengYu 介紹 Python Timer 的用法與範例,Python 的 Timer() 可以指定延遲一段時間去執行指定的函式,預設 Timer 只執行一次,觸發一次以後之後並不會再觸發,如果要多次重複觸發的話也可以參考本篇介紹的 RepeatingTimer 循環 Timer。

以下 Python Timer 的用法介紹將分為這幾部份,

  • Python Timer 基本用法
  • Python 取消 Timer
  • Timer 在 Python 2 跟 Python 3 的差別
  • 循環 Timer

那我們開始吧!

Python Timer 基本用法

以下是 Python Timer 基本用法,Python 2 跟 Python 3 都是這樣寫,threading.Timer() 會新建立一個 Timer 的執行緒,經過 interval 秒後就會呼叫傳入的函式,Timer() 第一個參數為要延遲多少秒來觸發
,如下範例中的 2 秒,也可以使用小數,例如:2.0,第二個參數為觸發時要呼叫的函式。之後可以使用 Timer.start() 來啟動計時器。

python3-timer.py
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from threading import Timer

def hello():
print("hello world")

t = Timer(2, hello)
t.start()

上述的 Timer 宣告跟 Timer.start() 啟動是分開寫計時器,如果不需要 Timer 回傳變數的話,也可以合併寫成一行,如下所示,

1
Timer(2, hello).start()

結果輸出如下,

1
hello world

Python 取消 Timer

Python 如果想要取消 Timer 的話,可以使用 Timer.cancel() 的成員函式,如下範例中的 Timer 原本會在 5 秒後被觸發,但是之後被 Timer.cancel() 取消所以沒有觸發。

python3-timer2.py
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from threading import Timer

def hello():
print("hello, world")

t = Timer(5, hello)
t.start()

t.cancel()

Timer 在 Python 2 跟 Python 3 的差別

這邊說明 Python 的 Timer 在 Python 2 和 Python 3 的差別,基本上這些差別不影響使用,主要是在它們內部實作不同,在 Python 2 中 _Timer 是 Thread 的子類,而 Timer 只是 _Timer 類的工廠方法 Factory Method。Python 2 的實作內容大概是這樣,

Python 2.x
1
2
3
4
5
6
# Python 2.x
def Timer(*args, **kwargs):
return _Timer(*args, **kwargs)

class _Timer(Thread):
pass

在 Python 3 中 Timer 是 Thread 的子類。Python 3 的實作內容大概是這樣,

Python 3.x
1
2
3
# Python 3.x
class Timer(Thread):
pass

循環 Timer

以下介紹 循環 Timer,最簡單的實作方式是在執行完函式後繼續設定 Timer,如下範例一開始設定 Timer 1 秒後執行 print_counter(),程式執行後經過 1 秒後執行 print_counter(),之後會判斷 count 小於 10 才會繼續設定 Timer 1 秒後執行 print_counter(),所以會反覆執行 10 次,

python3-timer3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from threading import Timer

count = 0
def print_counter():
global t, count
count += 1
print("count: " + str(count))

if count < 10:
t = Timer(1, print_counter)
t.start()

t = Timer(1, print_counter)
t.start()

結果輸出如下,

1
2
3
4
5
6
7
8
9
10
count: 1
count: 2
count: 3
count: 4
count: 5
count: 6
count: 7
count: 8
count: 9
count: 10

以上就完成了簡易型的循環 Timer,這樣還算堪用,但是上述的寫法是每次都另開新的 Timer 執行緒來執行同樣的函式,似乎效能不是很好,難道不能重複利用原本一開始建立的 Timer 執行緒嗎?

答案是可以的!接下來就要介紹怎麼寫一個 RepeatingTimer 循環 Timer 是重複利用原本一開始建立的 Timer 執行緒繼續去重複執行函式。

以下是 Python 2 的版本,RepeatingTimer 繼承了 threading._Timer 然後覆寫父類的 run 成員函式,覆寫 run 後,run 一開始跟原本的實作一樣,先等待 interval 秒,如果之後檢查沒有 set,沒有的話就呼叫 callback function,之後繼續等待 interval 秒,如此循環下去,

python-repeatingtimer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from threading import _Timer

def print_hello():
print("hello world")

class RepeatingTimer(_Timer):
def run(self):
self.finished.wait(self.interval)
while not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.wait(self.interval)

t = RepeatingTimer(2.0, print_hello)
t.start()

以下是 Python 3 的版本,RepeatingTimer 繼承了 threading.Timer 然後覆寫父類的 run 成員函式,其餘跟上述解釋一樣,

python3-repeatingtimer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from threading import Timer

def print_hello():
print("hello world")

class RepeatingTimer(Timer):
def run(self):
self.finished.wait(self.interval)
while not self.finished.is_set():
self.function(*self.args, **self.kwargs)
self.finished.wait(self.interval)

t = RepeatingTimer(2.0, print_hello)
t.start()

上述的 RepeatingTimer 要怎麼停止呢?就是要有另一個執行緒來執行 cancel(),如上例中的話就要這樣寫,

1
t.cancel()

以上就是 Python Timer 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
Python 新手入門教學懶人包