- 一、time和datetime模塊
- 二、logging模塊
PS:若是你想搜索安裝某個模塊或者發佈一個本身的模塊能夠到移步到:pypi.org/css
代碼示例以下:html
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)
複製代碼
運行結果以下:python
年: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
複製代碼
以下表所示,參考時間爲(20190314 13:53:41)nginx
符號 | 描述 | 示例 |
---|---|---|
%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))
複製代碼
運行結果以下:ruby
當前時間: 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']
複製代碼
大部分的程序都會有「記錄運行日誌的需求」,而日誌信息通常有這樣幾類:正常的程序運行日誌,調試,錯誤或警告信息的輸出等。而平常開發中咱們須要把日誌持久化到本地,進行一些觀察和統計,錯誤排查等,若是隻用print函數輸出的話,顯然有點捉襟見寸。在Python內置了一個日誌模塊:logging,它提供了標準的日誌接口,支持日誌分級和存儲。app
在開始正式學習logging前,咱們先了解下「日誌分級」,即:何時用什麼等級的日誌。以下表所示:socket
級別 | 建議何時使用 |
---|---|
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…
若是本文對你有所幫助,歡迎
留言,點贊,轉發
素質三連,謝謝😘~