- 一、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…
若是本文对你有所帮助,欢迎
留言,点赞,转发
素质三连,谢谢😘~