基本用法

下面的代码展示了logging最基本的用法。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- coding: utf-8 -*-
 
import logging
import sys
 
# 获取logger实例,如果参数为空则返回root logger
logger=logging.getLogger("AppName")
 
# 指定logger输出格式
formatter=logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
 
# 文件日志
file_handler=logging.FileHandler("test.log")
file_handler.setFormatter(formatter)  # 可以通过setFormatter指定输出格式
 
# 控制台日志
console_handler=logging.StreamHandler(sys.stdout)
console_handler.formatter=formatter  # 也可以直接给formatter赋值
 
# 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
 
# 指定日志的最低输出级别,默认为WARN级别
logger.setLevel(logging.INFO)
 
# 输出不同级别的log
logger.debug('this is debug info')
logger.info('this is information')
logger.warn('this is warning message')
logger.error('this is error message')
logger.fatal('this is fatal message, it is same as logger.critical')
logger.critical('this is critical message')
 
# 2016-10-08 21:59:19,493 INFO    : this is information
# 2016-10-08 21:59:19,493 WARNING : this is warning message
# 2016-10-08 21:59:19,493 ERROR   : this is error message
# 2016-10-08 21:59:19,493 CRITICAL: this is fatal message, it is same as logger.critical
# 2016-10-08 21:59:19,493 CRITICAL: this is critical message
 
# 移除一些日志处理器
logger.removeHandler(file_handler)

除了这些基本用法,还有一些常见的小技巧可以分享一下。

格式化输出日志

 
 
1
2
3
4
5
6
7
8
9
# 格式化输出
 
service_name="Booking"
logger.error('%s service is down!'%service_name)  # 使用python自带的字符串格式化,不推荐
logger.error('%s service is down!',service_name)  # 使用logger的格式化,推荐
logger.error('%s service is %s!',service_name,'down')  # 多参数格式化
logger.error('{} service is {}'.format(service_name,'down'))# 使用format函数,推荐
 
# 2016-10-08 21:59:19,493 ERROR   : Booking service is down!

记录异常信息

当你使用logging模块记录异常信息时,不需要传入该异常对象,只要你直接调用logger.error() 或者 logger.exception()就可以将当前异常记录下来。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
# 记录异常信息
 
try:
    1/0
except:
    # 等同于error级别,但是会额外记录当前抛出的异常堆栈信息
    logger.exception('this is an exception message')
 
# 2016-10-08 21:59:19,493 ERROR   : this is an exception message
# Traceback (most recent call last):
#   File "D:/Git/py_labs/demo/use_logging.py", line 45, in
#     1 / 0
# ZeroDivisionError: integer division or modulo by zero

logging配置要点

GetLogger()方法

这是最基本的入口,该方法参数可以为空,默认的logger名称是root,如果在同一个程序中一直都使用同名的logger,其实会拿到同一个实例,使用这个技巧就可以跨模块调用同样的logger来记录日志。

另外你也可以通过日志名称来区分同一程序的不同模块,比如这个例子。

 
 
1
2
logger=logging.getLogger("App.UI")
logger=logging.getLogger("App.Service")

Formatter日志格式

Formatter对象定义了log信息的结构和内容,构造时需要带两个参数:

  • 一个是格式化的模板fmt,默认会包含最基本的level和 message信息
  • 一个是格式化的时间样式datefmt,默认为 2003-07-08 16:49:45,896 (%Y-%m-%d %H:%M:%S)

fmt中允许使用的变量可以参考下表。

  • %(name)s Logger的名字
  • %(levelno)s 数字形式的日志级别
  • %(levelname)s 文本形式的日志级别
  • %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
  • %(filename)s 调用日志输出函数的模块的文件名
  • %(module)s 调用日志输出函数的模块名|
  • %(funcName)s 调用日志输出函数的函数名|
  • %(lineno)d 调用日志输出函数的语句所在的代码行
  • %(created)f 当前时间,用UNIX标准的表示时间的浮点数表示|
  • %(relativeCreated)d 输出日志信息时的,自Logger创建以来的毫秒数|
  • %(asctime)s 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896”。逗号后面的是毫秒
  • %(thread)d 线程ID。可能没有
  • %(threadName)s 线程名。可能没有
  • %(process)d 进程ID。可能没有
  • %(message)s 用户输出的消息

SetLevel 日志级别

Logging有如下级别: DEBUG,INFO,WARNING,ERROR,CRITICAL
默认级别是WARNING,logging模块只会输出指定level以上的log。这样的好处, 就是在项目开发时debug用的log,在产品release阶段不用一一注释,只需要调整logger的级别就可以了,很方便。

Handler 日志处理器

最常用的是StreamHandler和FileHandler, Handler用于向不同的输出端打log。
Logging包含很多handler, 可能用到的有下面几种

  • StreamHandler instances send error messages to streams (file-like objects).
  • FileHandler instances send error messages to disk files.
  • RotatingFileHandler instances send error messages to disk files, with support for maximum log file sizes and log file rotation.
  • TimedRotatingFileHandler instances send error messages to disk files, rotating the log file at certain timed intervals.
  • SocketHandler instances send error messages to TCP/IP sockets.
  • DatagramHandler instances send error messages to UDP sockets.
  • SMTPHandler instances send error messages to a designated email address.

Configuration 配置方法

logging的配置大致有下面几种方式。

  1. 通过代码进行完整配置,参考开头的例子,主要是通过getLogger方法实现。
  2. 通过代码进行简单配置,下面有例子,主要是通过basicConfig方法实现。
  3. 通过配置文件,下面有例子,主要是通过 logging.config.fileConfig(filepath)
logging.basicConfig

basicConfig()提供了非常便捷的方式让你配置logging模块并马上开始使用,可以参考下面的例子。具体可以配置的项目请查阅官方文档

 
 
1
2
3
4
5
6
7
8
9
10
import logging
 
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
 
logging.basicConfig(format='%(levelname)s:%(message)s',level=logging.DEBUG)
logging.debug('This message should appear on the console')
 
logging.basicConfig(format='%(asctime)s %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

备注: 其实你甚至可以什么都不配置直接使用默认值在控制台中打log,用这样的方式替换print语句对日后项目维护会有很大帮助。

通过文件配置logging

如果你希望通过配置文件来管理logging,可以参考这个官方文档。在log4net或者log4j中这是很常见的方式。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# logging.conf
[loggers]
keys=root
 
[logger_root]
level=DEBUG
handlers=consoleHandler
#,timedRotateFileHandler,errorTimedRotateFileHandler
 
#################################################
[handlers]
keys=consoleHandler,timedRotateFileHandler,errorTimedRotateFileHandler
 
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
 
[handler_timedRotateFileHandler]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=simpleFormatter
args=('debug.log','H')
 
[handler_errorTimedRotateFileHandler]
class=handlers.TimedRotatingFileHandler
level=WARN
formatter=simpleFormatter
args=('error.log','H')
 
#################################################
[formatters]
keys=simpleFormatter,multiLineFormatter
 
[formatter_simpleFormatter]
format=%(levelname)s%(threadName)s%(asctime)s:   %(message)s
datefmt=%H:%M:%S
 
[formatter_multiLineFormatter]
format=-------------------------%(levelname)s-------------------------
Time:      %(asctime)s
Thread:    %(threadName)s
File:      %(filename)s(line%(lineno)d)
Message:
%(message)s
 
datefmt=%Y-%m-%d%H:%M:%S

假设以上的配置文件放在和模块相同的目录,代码中的调用如下。

 
 
1
2
3
4
import os
filepath=os.path.join(os.path.dirname(__file__),'logging.conf')
logging.config.fileConfig(filepath)
returnlogging.getLogger()

日志重复输出的坑

你有可能会看到你打的日志会重复显示多次,可能的原因有很多,但总结下来无非就一个,日志中使用了重复的handler。

第一坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
import logging
 
logging.basicConfig(level=logging.DEBUG)
 
fmt='%(levelname)s:%(message)s'
console_handler=logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(fmt))
logging.getLogger().addHandler(console_handler)
 
logging.info('hello!')
 
# INFO:root:hello!
# INFO:hello!

上面这个例子出现了重复日志,因为在第3行调用basicConfig()方法时系统会默认创建一个handler,如果你再添加一个控制台handler时就会出现重复日志。

第二坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import logging
 
def get_logger():
    fmt='%(levelname)s:%(message)s'
    console_handler=logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter(fmt))
    logger=logging.getLogger('App')
    logger.setLevel(logging.INFO)
    logger.addHandler(console_handler)
    returnlogger
 
def call_me():
    logger=get_logger()
    logger.info('hi')
 
call_me()
call_me()
 
# INFO:hi
# INFO:hi
# INFO:hi

在这个例子里hi居然打印了三次,如果再调用一次call_me()呢?我告诉你会打印6次。why? 因为你每次调用get_logger()方法时都会给它加一个新的handler,你是自作自受。正常的做法应该是全局只配置logger一次。

第三坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import logging
 
def get_logger():
    fmt='%(levelname)s: %(message)s'
    console_handler=logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter(fmt))
    logger=logging.getLogger('App')
    logger.setLevel(logging.INFO)
    logger.addHandler(console_handler)
    returnlogger
 
def foo():
    logging.basicConfig(format='[%(name)s]: %(message)s')
    logging.warn('some module use root logger')
 
def main():
    logger=get_logger()
    logger.info('App start.')
    foo()
    logger.info('App shutdown.')
 
main()
 
# INFO: App start.
# [root]: some module use root logger
# INFO: App shutdown.
# [App]: App shutdown.

为嘛最后的App shutdown打印了两次?所以在Stackoverflow上很多人都问,我应该怎么样把root logger关掉,root logger太坑爹坑妈了。只要你在程序中使用过root logger,那么默认你打印的所有日志都算它一份。上面的例子没有什么很好的办法,我建议你招到那个没有经过大脑就使用root logger的人,乱棍打死他或者开除他。

如果你真的想禁用root logger,有两个不是办法的办法:

 
 
1
2
logging.getLogger().handlers=[]  # 删除所有的handler
logging.getLogger().setLevel(logging.CRITICAL)  # 将它的级别设置到最高

小结

Python中的日志模块作为标准库的一部分,功能还是比较完善的。个人觉得上手简单,另外也支持比如过滤,文件锁等高级功能,能满足大多数项目需求。

不过切记,小心坑。

Python中的logging模块

2016/11/27 · 基础知识 · logging

分享到:0
原文出处: cicaday   

最近修改了项目里的logging相关功能,用到了python标准库里的logging模块,在此做一些记录。主要是从官方文档和stackoverflow上查询到的一些内容。

基本用法

下面的代码展示了logging最基本的用法。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- coding: utf-8 -*-
 
import logging
import sys
 
# 获取logger实例,如果参数为空则返回root logger
logger=logging.getLogger("AppName")
 
# 指定logger输出格式
formatter=logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
 
# 文件日志
file_handler=logging.FileHandler("test.log")
file_handler.setFormatter(formatter)  # 可以通过setFormatter指定输出格式
 
# 控制台日志
console_handler=logging.StreamHandler(sys.stdout)
console_handler.formatter=formatter  # 也可以直接给formatter赋值
 
# 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
 
# 指定日志的最低输出级别,默认为WARN级别
logger.setLevel(logging.INFO)
 
# 输出不同级别的log
logger.debug('this is debug info')
logger.info('this is information')
logger.warn('this is warning message')
logger.error('this is error message')
logger.fatal('this is fatal message, it is same as logger.critical')
logger.critical('this is critical message')
 
# 2016-10-08 21:59:19,493 INFO    : this is information
# 2016-10-08 21:59:19,493 WARNING : this is warning message
# 2016-10-08 21:59:19,493 ERROR   : this is error message
# 2016-10-08 21:59:19,493 CRITICAL: this is fatal message, it is same as logger.critical
# 2016-10-08 21:59:19,493 CRITICAL: this is critical message
 
# 移除一些日志处理器
logger.removeHandler(file_handler)

除了这些基本用法,还有一些常见的小技巧可以分享一下。

格式化输出日志

 
 
1
2
3
4
5
6
7
8
9
# 格式化输出
 
service_name="Booking"
logger.error('%s service is down!'%service_name)  # 使用python自带的字符串格式化,不推荐
logger.error('%s service is down!',service_name)  # 使用logger的格式化,推荐
logger.error('%s service is %s!',service_name,'down')  # 多参数格式化
logger.error('{} service is {}'.format(service_name,'down'))# 使用format函数,推荐
 
# 2016-10-08 21:59:19,493 ERROR   : Booking service is down!

记录异常信息

当你使用logging模块记录异常信息时,不需要传入该异常对象,只要你直接调用logger.error() 或者 logger.exception()就可以将当前异常记录下来。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
# 记录异常信息
 
try:
    1/0
except:
    # 等同于error级别,但是会额外记录当前抛出的异常堆栈信息
    logger.exception('this is an exception message')
 
# 2016-10-08 21:59:19,493 ERROR   : this is an exception message
# Traceback (most recent call last):
#   File "D:/Git/py_labs/demo/use_logging.py", line 45, in
#     1 / 0
# ZeroDivisionError: integer division or modulo by zero

logging配置要点

GetLogger()方法

这是最基本的入口,该方法参数可以为空,默认的logger名称是root,如果在同一个程序中一直都使用同名的logger,其实会拿到同一个实例,使用这个技巧就可以跨模块调用同样的logger来记录日志。

另外你也可以通过日志名称来区分同一程序的不同模块,比如这个例子。

 
 
1
2
logger=logging.getLogger("App.UI")
logger=logging.getLogger("App.Service")

Formatter日志格式

Formatter对象定义了log信息的结构和内容,构造时需要带两个参数:

  • 一个是格式化的模板fmt,默认会包含最基本的level和 message信息
  • 一个是格式化的时间样式datefmt,默认为 2003-07-08 16:49:45,896 (%Y-%m-%d %H:%M:%S)

fmt中允许使用的变量可以参考下表。

  • %(name)s Logger的名字
  • %(levelno)s 数字形式的日志级别
  • %(levelname)s 文本形式的日志级别
  • %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
  • %(filename)s 调用日志输出函数的模块的文件名
  • %(module)s 调用日志输出函数的模块名|
  • %(funcName)s 调用日志输出函数的函数名|
  • %(lineno)d 调用日志输出函数的语句所在的代码行
  • %(created)f 当前时间,用UNIX标准的表示时间的浮点数表示|
  • %(relativeCreated)d 输出日志信息时的,自Logger创建以来的毫秒数|
  • %(asctime)s 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896”。逗号后面的是毫秒
  • %(thread)d 线程ID。可能没有
  • %(threadName)s 线程名。可能没有
  • %(process)d 进程ID。可能没有
  • %(message)s 用户输出的消息

SetLevel 日志级别

Logging有如下级别: DEBUG,INFO,WARNING,ERROR,CRITICAL
默认级别是WARNING,logging模块只会输出指定level以上的log。这样的好处, 就是在项目开发时debug用的log,在产品release阶段不用一一注释,只需要调整logger的级别就可以了,很方便。

Handler 日志处理器

最常用的是StreamHandler和FileHandler, Handler用于向不同的输出端打log。
Logging包含很多handler, 可能用到的有下面几种

  • StreamHandler instances send error messages to streams (file-like objects).
  • FileHandler instances send error messages to disk files.
  • RotatingFileHandler instances send error messages to disk files, with support for maximum log file sizes and log file rotation.
  • TimedRotatingFileHandler instances send error messages to disk files, rotating the log file at certain timed intervals.
  • SocketHandler instances send error messages to TCP/IP sockets.
  • DatagramHandler instances send error messages to UDP sockets.
  • SMTPHandler instances send error messages to a designated email address.

Configuration 配置方法

logging的配置大致有下面几种方式。

  1. 通过代码进行完整配置,参考开头的例子,主要是通过getLogger方法实现。
  2. 通过代码进行简单配置,下面有例子,主要是通过basicConfig方法实现。
  3. 通过配置文件,下面有例子,主要是通过 logging.config.fileConfig(filepath)
logging.basicConfig

basicConfig()提供了非常便捷的方式让你配置logging模块并马上开始使用,可以参考下面的例子。具体可以配置的项目请查阅官方文档

 
 
1
2
3
4
5
6
7
8
9
10
import logging
 
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
 
logging.basicConfig(format='%(levelname)s:%(message)s',level=logging.DEBUG)
logging.debug('This message should appear on the console')
 
logging.basicConfig(format='%(asctime)s %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

备注: 其实你甚至可以什么都不配置直接使用默认值在控制台中打log,用这样的方式替换print语句对日后项目维护会有很大帮助。

通过文件配置logging

如果你希望通过配置文件来管理logging,可以参考这个官方文档。在log4net或者log4j中这是很常见的方式。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# logging.conf
[loggers]
keys=root
 
[logger_root]
level=DEBUG
handlers=consoleHandler
#,timedRotateFileHandler,errorTimedRotateFileHandler
 
#################################################
[handlers]
keys=consoleHandler,timedRotateFileHandler,errorTimedRotateFileHandler
 
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
 
[handler_timedRotateFileHandler]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=simpleFormatter
args=('debug.log','H')
 
[handler_errorTimedRotateFileHandler]
class=handlers.TimedRotatingFileHandler
level=WARN
formatter=simpleFormatter
args=('error.log','H')
 
#################################################
[formatters]
keys=simpleFormatter,multiLineFormatter
 
[formatter_simpleFormatter]
format=%(levelname)s%(threadName)s%(asctime)s:   %(message)s
datefmt=%H:%M:%S
 
[formatter_multiLineFormatter]
format=-------------------------%(levelname)s-------------------------
Time:      %(asctime)s
Thread:    %(threadName)s
File:      %(filename)s(line%(lineno)d)
Message:
%(message)s
 
datefmt=%Y-%m-%d%H:%M:%S

假设以上的配置文件放在和模块相同的目录,代码中的调用如下。

 
 
1
2
3
4
import os
filepath=os.path.join(os.path.dirname(__file__),'logging.conf')
logging.config.fileConfig(filepath)
returnlogging.getLogger()

日志重复输出的坑

你有可能会看到你打的日志会重复显示多次,可能的原因有很多,但总结下来无非就一个,日志中使用了重复的handler。

第一坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
import logging
 
logging.basicConfig(level=logging.DEBUG)
 
fmt='%(levelname)s:%(message)s'
console_handler=logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(fmt))
logging.getLogger().addHandler(console_handler)
 
logging.info('hello!')
 
# INFO:root:hello!
# INFO:hello!

上面这个例子出现了重复日志,因为在第3行调用basicConfig()方法时系统会默认创建一个handler,如果你再添加一个控制台handler时就会出现重复日志。

第二坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import logging
 
def get_logger():
    fmt='%(levelname)s:%(message)s'
    console_handler=logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter(fmt))
    logger=logging.getLogger('App')
    logger.setLevel(logging.INFO)
    logger.addHandler(console_handler)
    returnlogger
 
def call_me():
    logger=get_logger()
    logger.info('hi')
 
call_me()
call_me()
 
# INFO:hi
# INFO:hi
# INFO:hi

在这个例子里hi居然打印了三次,如果再调用一次call_me()呢?我告诉你会打印6次。why? 因为你每次调用get_logger()方法时都会给它加一个新的handler,你是自作自受。正常的做法应该是全局只配置logger一次。

第三坑

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import logging
 
def get_logger():
    fmt='%(levelname)s: %(message)s'
    console_handler=logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter(fmt))
    logger=logging.getLogger('App')
    logger.setLevel(logging.INFO)
    logger.addHandler(console_handler)
    returnlogger
 
def foo():
    logging.basicConfig(format='[%(name)s]: %(message)s')
    logging.warn('some module use root logger')
 
def main():
    logger=get_logger()
    logger.info('App start.')
    foo()
    logger.info('App shutdown.')
 
main()
 
# INFO: App start.
# [root]: some module use root logger
# INFO: App shutdown.
# [App]: App shutdown.

为嘛最后的App shutdown打印了两次?所以在Stackoverflow上很多人都问,我应该怎么样把root logger关掉,root logger太坑爹坑妈了。只要你在程序中使用过root logger,那么默认你打印的所有日志都算它一份。上面的例子没有什么很好的办法,我建议你招到那个没有经过大脑就使用root logger的人,乱棍打死他或者开除他。

如果你真的想禁用root logger,有两个不是办法的办法:

 
 
1
2
logging.getLogger().handlers=[]  # 删除所有的handler
logging.getLogger().setLevel(logging.CRITICAL)  # 将它的级别设置到最高

小结

Python中的日志模块作为标准库的一部分,功能还是比较完善的。个人觉得上手简单,另外也支持比如过滤,文件锁等高级功能,能满足大多数项目需求。

不过切记,小心坑。

python logging method 02的更多相关文章

  1. python logging 日志轮转文件不删除问题

    前言 最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据. 分析 项目使用了 logg ...

  2. python logging 日志轮转文件不删除问题的解决方法

    项目使用了 logging 的 TimedRotatingFileHandler : #!/user/bin/env python # -*- coding: utf-8 -*- import log ...

  3. python logging详解及自动添加上下文信息

    之前写过一篇文章日志的艺术(The art of logging),提到了输出日志的时候记录上下文信息的重要性,我认为上下文信息包括: when:log事件发生的时间 where:log事件发生在哪个 ...

  4. 读懂掌握 Python logging 模块源码 (附带一些 example)

    搜了一下自己的 Blog 一直缺乏一篇 Python logging 模块的深度使用的文章.其实这个模块非常常用,也有非常多的滥用.所以看看源码来详细记录一篇属于 logging 模块的文章. 整个 ...

  5. 0x01 Python logging模块

    目录 Python logging 模块 前言 logging模块提供的特性 logging模块的设计过程 logger的继承 logger在逻辑上的继承结构 logging.basicConfig( ...

  6. python logging模块可能会令人困惑的地方

    python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...

  7. python logging 配置

    python logging 配置 在python中,logging由logger,handler,filter,formater四个部分组成,logger是提供我们记录日志的方法:handler是让 ...

  8. Python LOGGING使用方法

    Python LOGGING使用方法 1. 简介 使用场景 场景 适合使用的方法 在终端输出程序或脚本的使用方法 print 报告一个事件的发生(例如状态的修改) logging.info()或log ...

  9. python logging模块使用

    近来再弄一个小项目,已经到收尾阶段了.希望加入写log机制来增加程序出错后的判断分析.尝试使用了python logging模块. #-*- coding:utf-8 -*- import loggi ...

随机推荐

  1. Mahout 模糊kmeans

    Mahout  模糊KMeans 一.算法流程 模糊 C 均值聚类(FCM),即众所周知的模糊 ISODATA,是用隶属度确定每个数据点属于某个聚类的程度的一种聚类算法.1973 年,Bezdek 提 ...

  2. python的exec

    exec "一条python语句" 这样会执行python 语句.用于执行储存在字符串或文件中的Python语句. 当然 也可以 用 exec(str)这种方式, 总之一句话,尽量 ...

  3. 在自己的服务器上安装GitBook

    更新时间:2016-08-05 更新说明: 由于在 Linux 内核的机器上安装 Calibre 需要安装的依赖库过多,故不推荐在此类机器上使用格式转换功能.你可以阅读 在自己的电脑上安装GitBoo ...

  4. 【Android 应用开发】Android资源文件 - 使用资源存储字符串 颜色 尺寸 整型 布尔值 数组

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/19913755 . 一. Android资源文件简介 1 ...

  5. AndroidBinder进程间通信系统-android学习之旅(86)

    目录 前言及知识准备 Service组件结构 Clinet组件结构 与Binder驱动程序交互 总结 Binder进程间通信实例 问题 本次主要介绍Android平台下Binder进程间通信库.所谓通 ...

  6. SwipeRefreshLayout实现上拉下拉刷新

    1:在布局中添加SwipeRefreshLayout和Listview组件 [html] view plain copy <?xml version="1.0" encodi ...

  7. android使用ViewPager实现欢迎引导页

    android使用ViewPager实现欢迎引导页 大多数APP第一次启动的时候,都会有一个引导界面,左右滑动,到最后一张,用户点击才再次进入主界面.当第二次启动的时候,则直接进入主界面. 这种效果一 ...

  8. Android Data Binding代码实践(告别findViewById)(四)

    Data Binding实战(一) Data Binding语法解析(二) Data Binding高级用法(三) 好了,继前三篇学习了Data Binding之后,我们可以发现它的强大之处有这么几点 ...

  9. 使用schemaExport自动生成表结构

    一.Hibernate原生状态 ? 1 2 3 4 5 Configuration cfg = new Configuration().configure();   SchemaExport expo ...

  10. ruby rails_autolink不能加载的原因

    从rails 3.1.0开始,默认在ActionView::Helper::TextHelper中的auto_link方法已经被移除,放到了第三方的gem里:rails_autolink.遂想试一下其 ...