python的标准logging模块
参考:
管方文档:
http://docs.python.org/library/logging.html
网友文档
http://crazier9527.iteye.com/blog/290018
http://blog.csdn.net/fxjtoday/article/details/6307285
日志轮询
http://www.cnblogs.com/oubo/archive/2011/09/06/2394561.html
简单的例子
一、一般配置
import logging
import sys
logger = logging.getLogger("endlesscode") #类实例,每行日志endlesscode开头
formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S',) #日志格式
file_handler = logging.FileHandler("test.log") #指定日志文件 一个实例
file_handler.setFormatter(formatter) #设置日志文件日志格式
stream_handler = logging.StreamHandler(sys.stderr) #流输出到标准错误输出
logger.addHandler(file_handler) #日志记录到文件
logger.addHandler(stream_handler) #日志记录到标准错误输出
#logger.setLevel(logging.ERROR)
logger.error("fuckgfw")
logger.removeHandler(stream_handler)
logger.error("fuckgov")
二、配置文件方式
上面这段代码基本包含logging模块的基本功能,更好的方式,使用配置
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M',
filename='export.log',
filemode='w')
Formatter
Formatter对象定义了最终log信息的顺序,结构和内容.于基本的logging.Handler类不同,应用可以直接实例化formatter类,当然,如果需要你也可以子例化formatter以便定制它的一些行为.
构造函数接受两个可选参数:一个信息格式字符串和一个日期格式字符串.如果没有信息格式字符串,直接输出log信息.如果没有日期格式字符串,默认的格式是:%Y-%m-%d %H:%M:%S
Handler
Logging包含很多handler,最常用的也就是StreamHandler和FileHandler【终端和log文件】
SetLevel
Logging有如下级别: DEBUG,INFO,WARNING,ERROR,CRITICAL
默认级别是WARNING, logging模块只会输出指定level以上的log
这样的好处, 就是在项目开发时debug用的log, 在产品release阶段不用一一注释, 只需要调整logger的级别就可以了, 很方便的.
Configuration
Creating loggers, handlers, and formatters explicitly using Python code that calls the configuration methods listed above.
Creating a logging config file and reading it using the fileConfig() function.
Creating a dictionary of configuration information and passing it to the dictConfig() function.
第一种配置方法前面的code里面已经有了
第二种配置方法, 我觉得在项目里面是比较实用的, 通过编写配置文件, 在code里面只需要用fileConfig配置一下logging, 显得比较简洁.
三、项目实例
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M',
filename='export.log',
filemode='w')
# define a Handler which writes INFO messages or higher to the sys.stderr
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# set a format which is simpler for console use
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
# add the handler to the root logger
logging.getLogger('').addHandler(console)
四、简单测试
#vim test99.py
#!/bin/env ptyhon26
import sys
import logging
import os
import time
logger = logging.getLogger("endlesscode")
formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S',)
file_handler = logging.FileHandler("test.log")
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler(sys.stderr)
#stream_handler.setFormatter(formatter)#标准错误输出没有使用格式,如果开启则为endlesscode Sat, 22 Sep 2012 17:39:54 ERROR fuckgfw
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
logger.error("fuckgfw")
print os.uname()[1]
print os.getcwd()
print sys.argv[0]
print time.time()
1)吐到终端和LOG
# python test99.py
fuckgfw
s6.xxxx.com
/root
test99.py
1346654294.56
# cat test.log
endlesscode Mon, 03 Sep 2012 02:35:26 ERROR fuckgfw
修改
logger.error("fuckgfw")
logger.error(os.uname()[1])
logger.error(os.getcwd())
logger.error(sys.argv[0])
logger.error(time.time())
# python test99.py
fuckgfw
s6.xxxxxx.com
/root
test99.py
1346654420.18
# cat test.log
endlesscode Mon, 03 Sep 2012 02:38:14 ERROR fuckgfw
endlesscode Mon, 03 Sep 2012 02:40:20 ERROR fuckgfw
endlesscode Mon, 03 Sep 2012 02:40:20 ERROR s6.xxxxxx.com
endlesscode Mon, 03 Sep 2012 02:40:20 ERROR /root
endlesscode Mon, 03 Sep 2012 02:40:20 ERROR test99.py
endlesscode Mon, 03 Sep 2012 02:40:20 ERROR 1346654420.18
2)只吐到LOG
注释logger.addHandler(stream_handler)
# echo > test.log
# python test99.py
You have mail in /var/spool/mail/root
#终端没有信息吐出了
# cat test.log
endlesscode Mon, 03 Sep 2012 02:45:59 ERROR fuckgfw
endlesscode Mon, 03 Sep 2012 02:45:59 ERROR s6.xxxxxx.com
endlesscode Mon, 03 Sep 2012 02:45:59 ERROR /root
endlesscode Mon, 03 Sep 2012 02:45:59 ERROR test99.py
endlesscode Mon, 03 Sep 2012 02:45:59 ERROR 1346654759.78
LOG里面记录
3)只吐到终端,不吐到LOG
# vim test99.py
#logger.addHandler(file_handler)
logger.addHandler(stream_handler)
[root@s6 ~]# echo > test.log
[root@s6 ~]# python test99.py
fuckgfw
s6.xxxxxx.com
/root
test99.py
1346654919.03
[root@s6 ~]# cat test.log
[root@s6 ~]#
测试OK
五、使用配置文件测试
#!/bin/env ptyhon26
import sys
import logging
import os
import time
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M',
filename='test1.log',
filemode='w')
#终端配置
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)#设置在显示在每行前面的字符
logging.info("fuckgfw")
logging.info(os.uname()[1])
logging.info(os.getcwd())
logging.info(sys.argv[0])
logging.info(time.time())
[root@s6 ~]# python26 test99.py
root : INFO fuckgfw
root : INFO s6.xxxxxx.com
root : INFO /root
root : INFO test99.py
root : INFO 1346676131.17
[root@s6 ~]# cat test1.log
2012-09-03 08:42 root INFO fuckgfw
2012-09-03 08:42 root INFO s6.xxxxxx.com
2012-09-03 08:42 root INFO /root
2012-09-03 08:42 root INFO test99.py
2012-09-03 08:42 root INFO 1346676131.17
2)仅仅写在log里面不打印在终端
脚本
#!/bin/env ptyhon26
import sys
import logging
import os
import time
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M',
filename='test1.log',
filemode='w')
logging.info("fuckgfw")
logging.info(os.uname()[1])
logging.info(os.getcwd())
logging.info(sys.argv[0])
logging.info(time.time())
# echo > test1.log
[root@s6 ~]# cat test1.log
2012-09-03 08:53 root INFO fuckgfw
2012-09-03 08:53 root INFO s6.xxxxxx.com
2012-09-03 08:53 root INFO /root
2012-09-03 08:53 root INFO test99.py
2012-09-03 08:53 root INFO 1346676795.25
3)仅打印终端,不写入log
#!/bin/env ptyhon26
import sys
import logging
import os
import time
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M')
logging.info("fuckgfw")
logging.info(os.uname()[1])
logging.info(os.getcwd())
logging.info(sys.argv[0])
logging.info(time.time())
[root@s6 ~]# python26 test99.py
2012-09-03 09:02 root INFO fuckgfw
2012-09-03 09:02 root INFO s6.xxxxxx.com
2012-09-03 09:02 root INFO /root
2012-09-03 09:02 root INFO test99.py
2012-09-03 09:02 root INFO 1346677333.15
六、等级研究
等级 debug info warning
#!/bin/env ptyhon26
import sys
import logging
import os
import time
logging.basicConfig(level=logging.error,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M')
logging.info("fuckgfw")
logging.info(os.uname()[1])
logging.info(os.getcwd())
logging.info(sys.argv[0])
logging.info(time.time())
提升我们要记录的log等级为error
# python26 test99.py
无输出
提升我们输入信息等级为error
logging.error("fuckgfw")
logging.error(os.uname()[1])
logging.error(os.getcwd())
logging.error(sys.argv[0])
logging.error(time.time())
# python26 test99.py
无输出
修改该
logging.basicConfig(level=logging.DEBUG,
[root@s6 ~]# python26 test99.py
2012-09-03 09:10 root ERROR fuckgfw
2012-09-03 09:10 root ERROR s6.xxxxxx.com
2012-09-03 09:10 root ERROR /root
2012-09-03 09:10 root ERROR test99.py
2012-09-03 09:10 root ERROR 1346677843.06
没有输出到文件中
在脚本里通过logging.error和logging.info控制输出的等级
记录LOG则通logging.basicConfig记录到log文件或终端
成品,有吐到终端又记录到LOG
1 #!/bin/env ptyhon26 2 import sys 3 import logging 4 import os 5 import time 6 7 #log in logfile 8 logging.basicConfig(level=logging.DEBUG, 9 format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', 10 datefmt='%Y-%m-%d %H:%M', 11 filename=sys.argv[0]+'.log', 12 filemode='w') 13 14 #output to console 15 console = logging.StreamHandler() 16 console.setLevel(logging.INFO) 17 formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') 18 console.setFormatter(formatter) 19 logging.getLogger('').addHandler(console) 20 21 #use log level 22 logging.info("Jin") 23 logging.info(os.uname()[1]) 24 logging.error(os.uname()[1]) 25 logging.info(os.getcwd()) 26 logging.error(sys.argv[0])
[root@s6 ~]# cat test99.py.log
2012-09-04 08:35 root INFO fuckgfw
2012-09-04 08:35 root INFO s6.xxxxxx.com
2012-09-04 08:35 root INFO /root
2012-09-04 08:35 root INFO test99.py
2012-09-04 08:35 root INFO 1346762147.54
2012-09-04 08:35 root ERROR fuckgfw
2012-09-04 08:35 root ERROR s6.xxxxxx.com
2012-09-04 08:35 root ERROR /root
2012-09-04 08:35 root ERROR test99.py
2012-09-04 08:35 root ERROR 1346762147.54
七、日志轮询
- logging.handlers.RotatingFileHandler 这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是: RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) 其中filename和mode两个参数和FileHandler一样。 maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。 backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
- logging.handlers.TimedRotatingFileHandler 这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) 其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。 interval是时间间隔。 when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值: S 秒 M 分 H 小时 D 天 W 每星期(interval==0时代表星期一) midnight 每天凌晨
1 #coding=utf8 2 import sys 3 import os 4 import logging 5 import logging.handlers 6 from time import sleep as wait 7 8 program_name = 'log-test' 9 homedir = os.path.dirname(sys.argv[0]) 10 logpath = homedir+'/'+program_name+'.log' 11 12 #logging.basicConfig(level=logging.DEBUG, 13 # format='%(asctime)s %(levelname)-8s %(message)s', 14 # datefmt='%Y-%m-%d %H:%M', 15 # filename=logpath, 16 # filemode='a') 17 #console = logging.StreamHandler() 18 #console.setLevel(logging.ERROR) 19 #formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') 20 #console.setFormatter(formatter) 21 #logging.getLogger('').addHandler(console) 22 23 #new test 24 root = logging.getLogger() 25 if len(root.handlers) == 0: 26 level = logging.INFO 27 format = '%(asctime)s %(levelname)s %(module)s.%(funcName)s Line:%(lineno)d%(message)s' 28 handler = logging.handlers.TimedRotatingFileHandler(filename = logpath, 29 when = "S", 30 interval=10, 31 backupCount = 5) 32 fmt = logging.Formatter(format) 33 handler.setFormatter(fmt) 34 root.addHandler(handler) 35 root.setLevel(level) 36 37 38 def RunLoging(maxtime): 39 mx = 0 40 while mx<=maxtime: 41 print mx 42 logging.error("Logging Test: Time [ %s ]" % mx) 43 wait(1) 44 mx += 1 45 46 47 if __name__ == "__main__": 48 print logpath 49 RunLoging(120)