天天看點

pyhon處理時間,定時任務和啟動程式

你可以守在電腦旁邊檢視程式的運作,但不守着它運作就更爽了。 你可以使用定時任務在指定的時間運作,或者固定的間隔時間運作。 例如, 你的程式每隔一小時爬取一下網站,來檢測内容是否發生變化,或者在你睡覺的時候(每天淩晨4點)啟動一個CPU消耗很大的任務。 Python的 time 和 datetime modules 提供了這些功能。

你也可以編寫程式來啟動其他程式, 通過使用 subprocess 和 threading modules。 通常,編寫程式最快的方式是利用其他人已經寫好的應用程式。

The time Module

您計算機的系統時鐘設定為特定的日期,時間和時區。内置時間子產品允許您的Python程式讀取系統

目前時間的時鐘。 time.time() 和 time.sleep() 函數是 time module 中最有用的。

The time.time() Function

Unix紀元(Unix epoch) 是程式設計中常用的時間參考:上午12點1970年1月1日,協調世界時(UTC)。 time.time() function 傳回自該時刻起的秒數作為浮點值。(回想一下,浮點數隻是一個帶小數點的數字。)這個數字是稱為紀元時間戳。 例如,在互動中輸入以下内容 shell:

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.time()
1554271653.4386587
>>> 
           

Epoch時間戳可用于分析代碼效率,即測量一段代碼需要運作多長時間。調用time.time()計算開始時間,然後調用代碼,再計算結束時間。算出代碼運作消耗的時間:

#! /usr/bin/python3
import time

def calcProd():
    # Calculate the product of the first 100, 000 numbers.
    product = 1
    for i in range(1, 100000):
        product = product * i
    return product

startTime = time.time()
prod = calcProd()
endTime = time.time()
print('The result is %s digits long.' % (len(str(prod))))
print('Took %s seconds to calculate.' % (endTime - startTime))

# output
The result is 456569 digits long.
Took 3.525928497314453 seconds to calculate.
           

注意

分析代碼的另一種方法是使用提供的 cProfile.run() 函數比簡單的 time.time() 技術更具資訊性的細節。 cProfile.run() 的詳情可以參考這裡。

The time.sleep() Function

如果需要暫停程式一段時間,請調用 time.sleep() 函數并傳遞您希望程式保持暫停的秒數。在互動式shell中輸入以下内容:

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> for i in range(3):
...     print('Tick')
...     time.sleep(1)
...     print('Tock')
...     time.sleep(1)
... 
Tick
Tock
Tick
Tock
Tick
Tock
>>> time.sleep(5)
>>> 
           

for循環将列印 Tick ,暫停一秒,列印 Tock,暫停一秒,列印勾選,暫停,知道三次循環完。time.sleep() 函數将被阻塞 - 也就是說,它不會傳回和釋放你的程式執行其他代碼 - 直到你的秒數

傳遞給 time.sleep() 已經過去了。 例如,如果輸入 time.sleep(5) ,你會等待五秒後才看到下一個提示(>>>)。

請注意,在在IDLE中,按ctrl -C不會中斷 time.sleep() 調用。 IDLE會等到整個暫停結束後再提高KeyboardInterrupt 異常。 要解決這個問題,不是調用單個time.sleep(30) 暫停30秒,而是使用for循環30次調用time.sleep(1)。

如果你在這30秒内的某個時間按ctrl -C,你應該看到立即抛出KeyboardInterrupt異常。

Rounding Numbers

在處理時間時,您經常會遇到很多浮點值小數點後的數字。 為了使這些值更易于使用,您可以

使用 Python 的内置 round() 函數縮短它們,該函數将浮點數舍入到您指定的精度。 隻需傳入你想要的數字,加上一個可選的第二個參數,表示在deci-之後有多少位數你要把它繞到它。 如果省略第二個參數,round() 将您的數字四舍五入到最接近的整數。 輸入以下内容

互動式shell:

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> now = time.time()
>>> now
1554274051.5462723
>>> round(now, 2)
1554274051.55
>>> round(now, 4)
1554274051.5463
>>> round(now)
1554274052
>>> 
           

在導入時間并存儲 time.time() 之後,我們調用 round(now, 2) 現在四舍五入到小數點後的兩位數,round(now, 4) 到四舍五入小數點後的數字, round(now) 舍入到最接近的整數。

Project: Super Stopwatch

如果你想統計一個任務花了多少時間,沒有實體秒表,又很難找到一個現成的APP. 你可以用Python寫一個。

從高層次來看,這是您的計劃将要做的事情:

  • 跟蹤按下Enter鍵之間經過的時間,每次按鍵開始計時器上的新“lap”。
  • 記錄下圈數,總時間和單圈時間。

    這意味着您的代碼需要執行以下操作:

  • 在程式開始時以及每圈開始時, 通過調用 time.time() 查找目前時間并将其存儲為時間戳.
  • 保持一個計數器計數器并在每次使用者按下輸入時遞增它。
  • 通過減去時間戳來計算經過的時間。
  • 處理 KeyboardInterrupt 異常,以便使用者可以按ctrl -C退出。
#! /usr/bin/python3
# stopwatch.py - A simple stopwatch program.

import time

# Display the program's instructions.
print('Press ENTER to begin. Afterwards. press ENTER to "click" the stopwatch. Press Ctrl-C to quit.')
input()  # press Enter to begin
print('Started.')
startTime = time.time() # get the first lap's start time
lastTime = startTime
lapNum = 1

# Start tracking the lap times.
try:
    while True:
        input()
        lapTime = round(time.time() - lastTime, 2)
        totalTime = round(time.time() - startTime, 2)
        print('Lap #%s: %s (%s)' % (lapNum, totalTime, lapTime), end='')
        lapNum += 1
        lastTime = time.time() # reset the last lap time
except KeyboardInterrupt:
    # Handle the Ctrl-C exception to keep its error message from displaying.
    print('\nDone.')
           

将時間錯轉換成 datetime object

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.datetime.fromtimestamp(1000000)
datetime.datetime(1970, 1, 12, 21, 46, 40)
>>> import time
>>> datetime.datetime.fromtimestamp(time.time())
datetime.datetime(2019, 4, 3, 16, 33, 12, 603559)
>>> 
           

datatime object 可以對比時間

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> halloween2015 = datetime.datetime(2015, 10, 31, 0, 0, 0)
>>> newyears2016 = datetime.datetime(2016, 1, 1, 0, 0, 0)
>>> oct31_2015 = datetime.datetime(2015, 10, 31, 0, 0, 0)
>>> halloween2015 == oct31_2015
True
>>> halloween2015 > newyears2016
False
>>> newyears2016 > halloween2015
True
>>> newyears2016 != oct31_2015
True
>>> 
           

The timedelta Data Type

datetime module 也提供了一個 timedelta data type, 代表一個持續時間而不是一個時刻。

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> delta = datetime.timedelta(days=11, hours=10, minutes=9, seconds=8)
>>> delta.days,delta.seconds,delta.microseconds
(11, 36548, 0)
>>> delta.total_seconds()
986948.0
>>>