內容簡述:
- 1、time和datetime模組
- 2、logging模組
PS:如果你想搜尋安裝某個模組或者釋出一個自己的模組可以到移步到:pypi.org/
1、time和datetime時間模組
① 基本操作
程式碼示例如下:
import time, datetime
# 獲取當前時間
moment = time.localtime()
print("年:%s" % moment[0])
print("月:%s" % moment[1])
print("日:%s" % moment[2])
print("時:%s" % moment[3])
print("分:%s" % moment[4])
print("秒:%s" % (moment[5] + 1))
print("周幾:%s" % (moment[6] + 1))
print("一年第幾天:%s" % moment[7])
print("是否為夏令時:%s" % moment[8], end="\n\n")
# 格式化時間(這裡要注意strftime和strptime是不一樣的!!!)
moment1 = time.strftime('%Y-%m-%d %H:%M:%S')
moment2 = time.strftime('%a %b %d %H:%M:%S %Y', time.localtime())
moment3 = time.mktime(time.strptime(moment2, '%a %b %d %H:%M:%S %Y'))
print(moment1)
print(moment2)
print(moment3, end="\n\n")
# 獲得當前時間戳
print(time.time()) # 秒級
print(int(round(time.time() * 1000)), end="\n\n") # 毫秒級
# 獲得當前時間(時間陣列,還需strftime格式化下)
print(datetime.datetime.now(), end="\n\n")
# 時間戳轉換為時間
# 方法一:
moment4 = 1512184082
moment5 = time.localtime(moment4) # 轉換成時間陣列
print(time.strftime('%Y-%m-%d %H:%M:%S', moment5), end="\n\n") # 格式化
# 方法二:
moment6 = datetime.datetime.utcfromtimestamp(moment4)
print(moment6)
moment7 = moment6.strftime('%a %b %d %H:%M:%S %Y')
print(moment7, end="\n\n")
# 程式碼延遲執行
time.sleep(5)
複製程式碼
執行結果如下:
年:2019
月:3
日:14
時:11
分:41
秒:57
周幾:4
一年第幾天:73
是否為夏令時:0
2019-03-14 11:41:56
Thu Mar 14 11:41:56 2019
1552534916.0
1552534916.3338902
1552534916334
2019-03-14 11:41:56.333890
2017-12-02 11:08:02
2017-12-02 03:08:02
Sat Dec 02 03:08:02 2017
複製程式碼
② struct_time,字串,時間戳之間的轉換關係
③ Python中的時間日期格式化符號
如下表所示,參考時間為(20190314 13:53:41)
符號 | 描述 | 示例 |
---|---|---|
%y | 兩位數的年份表示(00-99) | 19 |
%Y | 四位數的年份表示(000-9999) | 2019 |
%m | 月份(01-12) | 03 |
%d | 月內中的一天(0-31) | 14 |
%H | 24小時制小時數(0-23) | 13 |
%I | 12小時制小時數(01-12) | 01 |
%M | 分鐘數(00=59) | 53 |
%S | 秒(00-59) | 41 |
%a | 星期幾的英文簡寫 | Thu |
%A | 星期幾的英文 | Thursday |
%b | 月份的英文簡寫 | Mar |
%B | 月份的英文 | March |
%x | 日期 | 03/14/19 |
%X | 時間 | 13:59:04 |
%c | 日期和時間 | Thu Mar 14 13:54:56 2019 |
%j | 一年中第幾天 | 073 |
%p | 以AM和PM的方式顯示上午還是下午 | PM |
%U | 一年中的第幾周,周天為一週的第一天 | 10 |
%W | 一年中的第幾周,週一為一週的第一天 | 10 |
%w | 一週中的第幾天,周天為0,週一為1 | 4 |
%z,%Z | 當前時區的名稱 | |
%% | %號自身 | % |
④ 一些實用的程式碼片段
下面提供一些很實用的程式碼片段,用到的時候複製貼上即可:
import datetime
import time
now = datetime.datetime.now()
# 獲得當前時間的前/後幾天,幾小時,幾秒,毫秒
# 如果是想獲得時間戳可以直接呼叫int(time.mktime(求出來的時間.timetuple()))
def fetch_before_time(time_type, value, strf="%Y-%m-%d %H:%M:%S"):
if time_type == 'days':
if value > 0:
return (datetime.datetime.now() + datetime.timedelta(days=value)).strftime(strf)
else:
return (datetime.datetime.now() - datetime.timedelta(days=value)).strftime(strf)
elif time_type == 'hours':
if value > 0:
return (datetime.datetime.now() + datetime.timedelta(hours=value)).strftime(strf)
else:
return (datetime.datetime.now() - datetime.timedelta(hours=value)).strftime(strf)
elif time_type == 'seconds':
if value > 0:
return (datetime.datetime.now() + datetime.timedelta(seconds=value)).strftime(strf)
else:
return (datetime.datetime.now() - datetime.timedelta(seconds=value)).strftime(strf)
elif time_type == 'microseconds':
if value > 0:
return (datetime.datetime.now() + datetime.timedelta(microseconds=value)).strftime(strf)
else:
return (datetime.datetime.now() - datetime.timedelta(microseconds=value)).strftime(strf)
# 獲得第二天凌晨的時間戳
def fetch_morning_timestamp():
return int(time.time()) + (144000 - (int(time.time())) % 86400)
# 構造一個由起始事件到結束時間間所有的日期列表
def init_date_list(begin_date, end_date):
date_list = []
begin_date = datetime.datetime.strptime(str(begin_date), "%Y%m%d")
end_date = datetime.datetime.strptime(str(end_date), "%Y%m%d")
while begin_date <= end_date:
date_str = begin_date.strftime("%Y%m%d")
date_list.append(date_str)
begin_date += datetime.timedelta(days=1)
return date_list
if __name__ == '__main__':
print("當前時間:", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
print(fetch_before_time('days', 3))
print(fetch_before_time('hours', -3))
print(fetch_before_time('seconds', 3))
print("第二天早上的時間戳:", fetch_morning_timestamp())
print("從20190101到20190301的日期列表:%s" % init_date_list(20190101, 20190301))
複製程式碼
執行結果如下:
當前時間: 2019-03-14 15:44:58
2019-03-17 15:44:58
2019-03-14 18:44:58
2019-03-14 15:45:01
第二天早上的時間戳: 1552665600
從20190101到20190301的日期列表:['20190101', '20190102',...過長省略... '20190226', '20190227', '20190228', '20190301']
複製程式碼
2、logging日誌模組
大部分的程式都會有「記錄執行日誌的需求」,而日誌資訊一般有這樣幾類:正常的程式執行日誌,除錯,錯誤或警告資訊的輸出等。而日常開發中我們需要把日誌持久化到本地,進行一些觀察和統計,錯誤排查等,如果只用print函式輸出的話,顯然有點捉襟見寸。在Python內建了一個日誌模組:logging,它提供了標準的日誌介面,支援日誌分級和儲存。
① 日誌分級
在開始正式學習logging前,我們先了解下「日誌分級」,即:什麼時候用什麼等級的日誌。如下表所示:
級別 | 建議什麼時候使用 |
---|---|
DEBUG | 詳細的資訊,常用於問題診斷 |
INFO | 記錄關鍵節點資訊,用於確認程式是否按照預期執行 |
WARNING | 程式還是正常執行,但某些不期望的事情發生時記錄的資訊(如磁碟可用空間較低) |
ERROR | 由於更嚴重的問題導致某些功能不能正常執行時記錄的資訊 |
CRITICAL | 發生嚴重錯誤,導致程式不能繼續執行時記錄的資訊 |
列印各種級別的程式碼示例如下:
import logging
if __name__ == '__main__':
# 獲得一個Logger
logger = logging.getLogger("Test")
# logging提供的簡單的配置方法,自行配置的話需要手動新增handler
logging.basicConfig()
# 設定輸出的log級別(大於或等於此級別的才會輸出),預設級別Warning
logger.setLevel(logging.INFO)
logger.debug("=== Debug 級別的資訊 ===") # 不會輸出
logger.info("=== Info 級別的資訊 ===")
logger.warning("=== Warning 級別的資訊 ===")
logger.error("=== Error 級別的資訊 ===")
logger.critical("=== Critical 級別的資訊 ===")
複製程式碼
執行結果如下:
INFO:Test:=== Info 級別的資訊 ===
WARNING:Test:=== Warning 級別的資訊 ===
ERROR:Test:=== Error 級別的資訊 ===
CRITICAL:Test:=== Critical 級別的資訊 ===
複製程式碼
② 將日誌寫入到檔案
日誌預設是輸出到Console(螢幕)上,如果我們想把詳細的日誌輸出到log檔案裡,則需要用到handler
了,理論上可以把日誌輸出到各種流中,stderr、檔案、socket等都可以,在logging中已經將各種流handler封裝好了,你也可以繼承StreamHandler類自己做一些定製,簡單的把日誌寫入到檔案中的程式碼示例如下:
import logging
if __name__ == '__main__':
logger = logging.getLogger("Test")
logger.setLevel(logging.INFO)
# 輸出到控制檯
logger.addHandler(logging.StreamHandler())
# 輸出到檔案
logger.addHandler(logging.FileHandler('test.log', encoding='UTF-8'))
logger.debug("=== Debug 級別的資訊 ===")
logger.info("=== Info 級別的資訊 ===")
logger.warning("=== Warning 級別的資訊 ===")
logger.error("=== Error 級別的資訊 ===")
logger.critical("=== Critical 級別的資訊 ===")
複製程式碼
執行結果如下(同時在目錄下生成了一個test.log的檔案):
=== Info 級別的資訊 ===
=== Warning 級別的資訊 ===
=== Error 級別的資訊 ===
=== Critical 級別的資訊 ===
複製程式碼
嗯,你可能有這樣的需求,Console列印Warning以上的日誌,而log檔案儲存Debug級別以上的日誌,那麼可以修改下上面的程式碼,修改後的程式碼如下:
if __name__ == '__main__':
logger = logging.getLogger("Test")
logger.setLevel(logging.INFO)
# 輸出到控制檯
s_handler = logging.StreamHandler()
s_handler.setLevel(logging.WARNING)
logger.addHandler(s_handler)
# 輸出到檔案
f_handler = logging.FileHandler('test.log', encoding='UTF-8')
f_handler.setLevel(logging.DEBUG)
logger.addHandler(f_handler)
logger.debug("=== Debug 級別的資訊 ===")
logger.info("=== Info 級別的資訊 ===")
logger.warning("=== Warning 級別的資訊 ===")
logger.error("=== Error 級別的資訊 ===")
logger.critical("=== Critical 級別的資訊 ===")
複製程式碼
執行結果如下:
# 控制檯輸出:
=== Warning 級別的資訊 ===
=== Error 級別的資訊 ===
=== Critical 級別的資訊 ===
# test.log檔案:
=== Info 級別的資訊 ===
=== Warning 級別的資訊 ===
=== Error 級別的資訊 ===
=== Critical 級別的資訊 ===
複製程式碼
③ 定製日誌輸出格式
糾結完輸出到那裡,接著就輸出日誌的格式了,日誌一般都是比較規範的,比如日誌列印的時間,型別等,而不會像我們這樣隨意拼接一段字串,對於日誌格式的定製可以通過
logging模組
的Formatter元件
來定製。basicConfig()
中的handler 自帶一個formatter,通過logging.basicConfig(**kwargs)函式
進行定製,該函式可接收的關鍵字引數如下表所示。
引數 | 描述 |
---|---|
filename | 指定日誌輸出目標檔案的檔名,設定後資訊就不會列印到控制檯 |
filemode | 指定日誌檔案的開啟模式,預設為'a',設定了filename這個才會生效 |
format | 指定日誌格式字串,即指定日誌輸出時所包含的欄位資訊以及它們的順序 |
datefmt | 指定日期/時間格式,該選項要在format中包含時間欄位%(asctime)s時才有效 |
level | 指定日誌器的日誌級別 |
stream | 指定日誌輸出目標stream,不能和filename同時使用否則會引起ValueError異常 |
style | Python 3.2新增,預設'%'指定format格式字串的風格,可取值為'%'、'{'和'$' |
format格式字串的欄位列表如下表所示:
引數 | 描述 |
---|---|
%(asctime)s | 日誌發生的時間--人類可讀時間,如:2003-07-08 16:49:45,896 |
%(created)f | 日誌發生的時間--時間戳,就是當時呼叫time.time()函式返回的值 |
%(relativeCreated)d | 日誌發生的時間相對於logging模組載入時間的相對毫秒數 |
%(msecs)d | 日誌發生時間的毫秒部分 |
%(levelname)s | 該日誌記錄的文字形式的日誌級別('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL') |
%(levelno)s | 該日誌記錄的數字形式的日誌級別(10, 20, 30, 40, 50) |
%(name)s | 所使用的日誌器名稱,預設是'root',因為預設使用的是 rootLogger |
%(message)s | 日誌記錄的文字內容,通過 msg % args計算得到的 |
%(pathname)s | 呼叫日誌記錄函式的原始碼檔案的全路徑 |
%(filename)s | pathname的檔名部分,包含檔案字尾 |
%(module)s | filename的名稱部分,不包含字尾 |
%(lineno)d | 呼叫日誌記錄函式的原始碼所在的行號 |
%(funcName)s | 呼叫日誌記錄函式的函式名 |
%(process)d | 程式ID |
%(processName)s | 程式名稱,Python 3.1新增 |
%(thread)d | 執行緒ID |
%(thread)s | 執行緒名稱 |
簡單的使用程式碼示例如下:
import logging
if __name__ == '__main__':
logger = logging.getLogger("Test")
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(process)d:%(processName)s- %(levelname)s === %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %p")
logger.debug("Debug 級別的資訊")
logger.info("Info 級別的資訊")
logger.warning("Warning 級別的資訊")
logger.error("Error 級別的資訊")
logger.critical("Critical 級別的資訊")
複製程式碼
執行結果如下:
2019-03-14 16:39:02 PM 8628:MainProcess- INFO === Info 級別的資訊
2019-03-14 16:39:02 PM 8628:MainProcess- WARNING === Warning 級別的資訊
2019-03-14 16:39:02 PM 8628:MainProcess- ERROR === Error 級別的資訊
2019-03-14 16:39:02 PM 8628:MainProcess- CRITICAL === Critical 級別的資訊
複製程式碼
另外要注意一點basicConfig沒有設定編碼的屬性,如果想把日誌寫入到檔案裡,而日誌裡又有中文的話,只能通過一開始那種設定FileHandler物件的方式!除了通過basicConfig()設定日誌格式,還可以自定義一個Formatter物件,然後呼叫
setFormatter
函式進行設定。使用程式碼示例如下:
import logging
if __name__ == '__main__':
logger = logging.getLogger("Test")
logger.setLevel(logging.INFO)
# 自定義Formatter物件
fmt = logging.Formatter("%(asctime)s %(process)d:%(processName)s- %(levelname)s === %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %p")
# 輸出到控制檯
s_handler = logging.StreamHandler()
s_handler.setLevel(logging.WARNING)
s_handler.setFormatter(fmt)
logger.addHandler(s_handler)
# 輸出到檔案
f_handler = logging.FileHandler('test.log', encoding='UTF-8')
f_handler.setLevel(logging.DEBUG)
f_handler.setFormatter(fmt)
logger.addHandler(f_handler)
logger.debug("Debug 級別的資訊")
logger.info("Info 級別的資訊")
logger.warning("Warning 級別的資訊")
logger.error("Error 級別的資訊")
logger.critical("Critical 級別的資訊")
複製程式碼
執行結果如下:
# 控制檯輸出:
2019-03-14 16:41:09 PM 11312:MainProcess- WARNING === Warning 級別的資訊
2019-03-14 16:41:09 PM 11312:MainProcess- ERROR === Error 級別的資訊
2019-03-14 16:41:09 PM 11312:MainProcess- CRITICAL === Critical 級別的資訊
# test.log檔案:
2019-03-14 16:41:09 PM 11312:MainProcess- INFO === Info 級別的資訊
2019-03-14 16:41:09 PM 11312:MainProcess- WARNING === Warning 級別的資訊
2019-03-14 16:41:09 PM 11312:MainProcess- ERROR === Error 級別的資訊
2019-03-14 16:41:09 PM 11312:MainProcess- CRITICAL === Critical 級別的資訊
複製程式碼
logging除了Handler
和Formatter
兩個元件外還有,Filter
和LoggerAdapter
元件,不過用得
不多,有興趣的同學可以自行到官方文件進行查閱:docs.python.org/3/library/l…
如果本文對你有所幫助,歡迎
留言,點贊,轉發
素質三連,謝謝?~