wordpress网站多语言,友情链接的定义,wordpress ping服务插件,购物网站开发的背景在现实生活中#xff0c;记录日志非常重要。银行转账时会有转账记录#xff1b;如果有出现什么问题#xff0c;人们可以通过日志数据来搞清楚到底发生了什么。 对于系统开发、调试以及运行#xff0c;记录日志都是同样的重要。如果没有日志记录#xff0c;程序崩溃时你… 在现实生活中记录日志非常重要。银行转账时会有转账记录如果有出现什么问题人们可以通过日志数据来搞清楚到底发生了什么。 对于系统开发、调试以及运行记录日志都是同样的重要。如果没有日志记录程序崩溃时你几乎就没办法弄明白到底发生了什么事情。1、简单使用import logging
logging.debug(debug message)
logging.info(info message)
logging.warn(warn message)
logging.error(error message)
logging.critical(critical message)执行结果WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message默认情况下logging模块将日志打印到屏幕上(stdout)日志级别为WARNING(即只有日志级别高于WARNING的日志信息才会输出)日志格式如下图所示1.1 日志级别级别数字形式何时使用DEBUG10详细信息典型地调试问题时会感兴趣。INFO20证明事情按预期工作。WARNING30表明发生了一些意外或者不久的将来会发生问题如‘磁盘满了’。软件还是在正常工作。ERROR40由于更严重的问题CRITICAL50严重错误表明软件已软件已不能执行一些功能了。不能继续运行了。NOSET0getattr日志、记录级。upper()1.2 简单配置import logging
# 通过下面的方式进行简单配置输出方式与日志级别
logging.basicConfig(filenamelogger.log, levellogging.INFO)
logging.debug(debug message)
logging.info(info message)
logging.warn(warn message)
logging.error(error message)
logging.critical(critical message)执行结果标准输出(屏幕)未显示任何信息发现当前工作目录下生成了logger.log内容如下INFO:root:info message
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message因为通过levellogging.INFO设置日志级别为INFO所以所有的日志信息均输出出来了。2、重要的概念Logger 记录器暴露了应用程序代码能直接使用的接口。Handler 处理器将记录器产生的日志记录发送至合适的目的地。Filter 过滤器提供了更好的粒度控制它可以决定输出哪些日志记录。Formatter 格式化器指明了最终输出中日志记录的布局。1.2.1 Logger 记录器Logger是一个树形层级结构在使用接口debuginfowarnerrorcritical之前必须创建Logger实例即创建一个记录器如果没有显式的进行创建则默认创建一个root logger并应用默认的日志级别(WARN)处理器Handler(StreamHandler即将日志信息打印输出在标准输出上)和格式化器Formatter(默认的格式即为第一个简单使用程序中输出的格式)。创建方法: logger logging.getLogger(logger_name)创建Logger实例后可以使用以下方法进行日志级别设置增加处理器Handler。logger.setLevel(logging.ERROR) # 设置日志级别为ERROR即只有日志级别大于等于ERROR的日志才会输出logger.addHandler(handler_name) # 为Logger实例增加一个处理器
logger.removeHandler(handler_name) # 为Logger实例删除一个处理器2.2 Handler 处理器Handler处理器类型有很多种比较常用的有三个StreamHandlerFileHandlerNullHandler详情可以访问Python logging.handlers创建StreamHandler之后可以通过使用以下方法设置日志级别设置格式化器Formatter增加或删除过滤器Filter。ch.setLevel(logging.WARN) # 指定日志级别低于WARN级别的日志将被忽略
ch.setFormatter(formatter_name) # 设置一个格式化器formatter
ch.addFilter(filter_name) # 增加一个过滤器可以增加多个
ch.removeFilter(filter_name) # 删除一个过滤器StreamHandler创建方法: sh logging.StreamHandler(streamNone)FileHandler创建方法: fh logging.FileHandler(filename, modea, encodingNone, delayFalse)NullHandlerNullHandler类位于核心logging包不做任何的格式化或者输出。本质上它是个“什么都不做”的handler由库开发者使用。2.3 Formatter 格式化器使用Formatter对象设置日志信息最后的规则、结构和内容默认的时间格式为%Y-%m-%d %H:%M:%S。创建方法: formatter logging.Formatter(fmtNone, datefmtNone)其中fmt是消息的格式化字符串datefmt是日期字符串。如果不指明fmt将使用%(message)s。如果不指明datefmt将使用ISO8601日期格式。2.4 Filter 过滤器Handlers和Loggers可以使用Filters来完成比级别更复杂的过滤。Filter基类只允许特定Logger层次以下的事件。例如用‘A.B’初始化的Filter允许Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等记录的事件logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字符串来初始化所有的事件都接受。创建方法: filter logging.Filter(name)以下是相关概念总结:熟悉了这些概念之后有另外一个比较重要的事情必须清楚即Logger是一个树形层级结构;Logger可以包含一个或多个Handler和Filter即Logger与Handler或Fitler是一对多的关系;一个Logger实例可以新增多个Handler一个Handler可以新增多个格式化器或多个过滤器而且日志级别将会继承。 3、Logging工作流程第一次导入logging模块或使用reload函数重新导入logging模块logging模块中的代码将被执行这个过程中将产生logging日志系统的默认配置。自定义配置(可选)。logging标准模块支持三种配置方式: dictConfigfileConfiglisten。其中dictConfig是通过一个字典进行配置LoggerHandlerFilterFormatterfileConfig则是通过一个文件进行配置而listen则监听一个网络端口通过接收网络数据来进行配置。当然除了以上集体化配置外也可以直接调用LoggerHandler等对象中的方法在代码中来显式配置。使用logging模块的全局作用域中的getLogger函数来得到一个Logger对象实例(其参数即是一个字符串表示Logger对象实例的名字即通过该名字来得到相应的Logger对象实例)。使用Logger对象中的debuginfoerrorwarncritical等方法记录日志信息。4、logging模块使用过程4.1 logging模块处理流程判断日志的等级是否大于Logger对象的等级如果大于则往下执行否则流程结束。产生日志。第一步判断是否有异常如果有则添加异常信息。第二步处理日志记录方法(如debuginfo等)中的占位符即一般的字符串格式化处理。使用注册到Logger对象中的Filters进行过滤。如果有多个过滤器则依次过滤只要有一个过滤器返回假则过滤结束且该日志信息将丢弃不再处理而处理流程也至此结束。否则处理流程往下执行。在当前Logger对象中查找Handlers如果找不到任何Handler则往上到该Logger对象的父Logger中查找如果找到一个或多个Handler则依次用Handler来处理日志信息。但在每个Handler处理日志信息过程中会首先判断日志信息的等级是否大于该Handler的等级如果大于则往下执行(由Logger对象进入Handler对象中)否则处理流程结束。执行Handler对象中的filter方法该方法会依次执行注册到该Handler对象中的Filter。如果有一个Filter判断该日志信息为假则此后的所有Filter都不再执行而直接将该日志信息丢弃处理流程结束。 使用Formatter类格式化最终的输出结果。 注Formatter同上述第2步的字符串格式化不同它会添加额外的信息比如日志产生的时间产生日志的源代码所在的源文件的路径等等。真正地输出日志信息(到网络文件终端邮件等)。至于输出到哪个目的地由Handler的种类来决定。注以上内容摘抄自第三条参考资料内容略有改动转载特此声明。5、日志配置5.1 配置方式显式创建记录器Logger、处理器Handler和格式化器Formatter并进行相关设置通过简单方式进行配置使用basicConfig()函数直接进行配置通过配置文件进行配置使用fileConfig()函数读取配置文件通过配置字典进行配置使用dictConfig()函数读取配置信息通过网络进行配置使用listen()函数进行网络配置。5.2 basicConfig关键字参数关键字描述filename创建一个FileHandler使用指定的文件名而不是使用StreamHandler。filemode如果指明了文件名指明打开文件的模式如果没有指明filemode默认为a。formathandler使用指明的格式化字符串。datefmt使用指明的日期时间格式。level指明根logger的级别。stream使用指明的流来初始化StreamHandler。该参数与filename不兼容如果两个都有stream被忽略。5.3 有用的format格式格式描述%(name)sLogger的名字%(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用户输出的消息5.4 配置示例5.4.1 显式配置使用程序logger.py如下:import logging
# create logger
logger_name example
file_log accesss.log
logger logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
# create file handler
fh logging.FileHandler(file_log)
fh.setLevel(logging.WARN)
# create formatter
fmt %(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s
datefmt %a %d %b %Y %H:%M:%S
formatter logging.Formatter(fmt, datefmt)
# add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)
# print log info
logger.debug(debug message)
logger.info(info message)
logger.warn(warn message)
logger.error(error message)
logger.critical(critical message)5.4.2 文件配置配置文件logging.conf如下:[loggers]
keysroot,example01
[logger_root]
levelDEBUG
handlershand01,hand02
[logger_example01]
handlershand01,hand02
qualnameexample01
propagate0
[handlers]
keyshand01,hand02
[handler_hand01]
classStreamHandler
levelINFO
formatterform02
args(sys.stderr,)
[handler_hand02]
classFileHandler
levelDEBUG
formatterform01
args(log.log, a)
[formatters]
keysform01,form02
[formatter_form01]
format%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s使用程序logger.py如下:import logging
import logging.config
logging.config.fileConfig(logging.conf)
# create logger
logger_name example
logger logging.getLogger(logger_name)
logger.debug(debug message)
logger.info(info message)
logger.warn(warn message)
logger.error(error message)
logger.critical(critical message)5.4.3 字典配置import logging
import logging.config
logger logging.getLogger(__name__)
# load config from file
# logging.config.fileConfig(logging.ini, disable_existing_loggersFalse)
# or, for dictConfig
logging.config.dictConfig({version: 1, disable_existing_loggers: False, # this fixes the problemformatters: {standard: {format: %(asctime)s [%(levelname)s] %(name)s: %(message)s},},handlers: {default: {level:INFO, class:logging.StreamHandler,}, },loggers: {: { handlers: [default], level: INFO, propagate: True }}
})
logger.info(It works!)5.4.4 监听配置可以使用logging.config.listen(portDEFAULT_LOGGING_CONFIG_PORT)进行完善本文。5.4.5 JSON配置配置文件logging.json如下{version: 1,disable_existing_loggers: false,formatters: {simple: {format: %(asctime)s - %(name)s - %(levelname)s - %(message)s}},handlers: {console: {class: logging.StreamHandler,level: DEBUG,formatter: simple,stream: ext://sys.stdout},info_file_handler: {class: logging.handlers.RotatingFileHandler,level: INFO,formatter: simple,filename: info.log,maxBytes: 10485760,backupCount: 20,encoding: utf8},error_file_handler: {class: logging.handlers.RotatingFileHandler,level: ERROR,formatter: simple,filename: errors.log,maxBytes: 10485760,backupCount: 20,encoding: utf8}},loggers: {my_module: {level: ERROR,handlers: [console],propagate: no}},root: {level: INFO,handlers: [console, info_file_handler, error_file_handler]}
}使用程序logger.py如下:import json
import logging.configdef setup_logging(default_pathlogging.json, default_levellogging.INFO,env_keyLOG_CFG
):Setup logging configurationpath default_pathvalue os.getenv(env_key, None)if value:path valueif os.path.exists(path):with open(path, rt) as f:config json.load(f)logging.config.dictConfig(config)else:logging.basicConfig(leveldefault_level)5.4.6 YAML配置配置文件logging.yaml如下 ---
version: 1
disable_existing_loggers: False
formatters:simple:format: %(asctime)s - %(name)s - %(levelname)s - %(message)s
handlers:console:class: logging.StreamHandlerlevel: DEBUGformatter: simplestream: ext://sys.stdoutinfo_file_handler:class: logging.handlers.RotatingFileHandlerlevel: INFO formatter: simplefilename: info.logmaxBytes: 10485760 # 10MBbackupCount: 20encoding: utf8error_file_handler:class: logging.handlers.RotatingFileHandlerlevel: ERROR formatter: simplefilename: errors.logmaxBytes: 10485760 # 10MBbackupCount: 20encoding: utf8
loggers:my_module:level: ERRORhandlers: [console]propagate: no
root:level: INFOhandlers: [console, info_file_handler, error_file_handler]
...使用程序logger.py如下:import os
import logging.config
import yaml
def setup_logging(default_pathlogging.yaml, default_levellogging.INFO,env_keyLOG_CFG
):Setup logging configurationpath default_pathvalue os.getenv(env_key, None)if value:path valueif os.path.exists(path):with open(path, rt) as f:config yaml.load(f.read())logging.config.dictConfig(config)else:lo6、使用 __name__ 作为 logger 的名称虽然不是非得将 logger 的名称设置为 __name__ 但是这样做会给我们带来诸多益处。在 python 中变量 __name__ 的名称就是当前模块的名称。比如在模块 “foo.bar.my_module” 中调用 logger.getLogger(__name__) 等价于调用logger.getLogger(“foo.bar.my_module”) 。当你需要配置 logger 时你可以配置到 “foo” 中这样包 foo 中的所有模块都会使用相同的配置。当你在读日志文件的时候你就能够明白消息到底来自于哪一个模块。7、捕捉异常并使用 traceback 记录它出问题的时候记录下来是个好习惯但是如果没有 traceback 那么它一点儿用也没有。你应该捕获异常并用 traceback 把它们记录下来。比如下面这个例子使用参数 exc_infotrue 调用 logger 方法, traceback 会输出到 logger 中。你可以看到下面的结果 try:open(/path/to/does/not/exist, rb)
except (SystemExit, KeyboardInterrupt):raise
except Exception, e:logger.error(Failed to open file, exc_infoTrue)你也可以调用 logger.exception(msg, _args)它等价于 logger.error(msg, exc_infoTrue, _args)。千万不要在模块层次获取 Logger除非 disable_existing_loggers 被设置为 False你可以看到很多在模块层次获取 logger 的例子在这篇文章我也使用了很多但这仅仅为了让示例更短一些。它们看上去没什么坏处但事实上这儿是有陷阱的 – 如果你像这样在模块中使用 LoggerPython 会保留从文件中读入配置前所有创建的所有 logger。my_module.py import logging
logger logging.getLogger(__name__)
def foo():logger.info(Hi, foo)
class Bar(object):def bar(self):logger.info(Hi, bar)
main.py
import logginglogger logging.getLogger(__name__)def foo():logger.info(Hi, foo)class Bar(object):def bar(self):logger.info(Hi, bar)本应该在日志中看到记录但是你却什么也没有看到。为什么呢这就是因为你在模块层次创建了 logger然后你又在加载日志配置文件之前就导入了模块。logging.fileConfig 与 logging.dictConfig 默认情况下会使得已经存在的 logger 失效。所以这些配置信息不会应用到你的 Logger 上。你最好只在你需要 logger 的时候才获得它。反正创建或者取得 logger 的成本很低。你可以这样写你的代码 import loggingdef foo():logger logging.getLogger(__name__)logger.info(Hi, foo)class Bar(object):def __init__(self, loggerNone):self.logger logger or logging.getLogger(__name__)def bar(self):self.logger.info(Hi, bar)这样logger 就会在你加载配置后才会被创建。这样配置信息就可以正常应用。python2.7 之后的版本中 fileConfg 与 dictConfig 都新添加了 “disable_existing_loggers” 参数将其设置为 False上面提到的问题就可以解决了。例如8、使用旋转文件句柄如果你用 FileHandler 写日志文件的大小会随着时间推移而不断增大。最终有一天它会占满你所有的磁盘空间。为了避免这种情况出现你可以在你的生成环境中使用 RotatingFileHandler 替代 FileHandler。9、如果你有多个服务器可以启用一个专用的日志服务器当你有多个服务器和不同的日志文件时你可以创建一个集中式的日志系统来收集重要的大多数情况是警告或者错误消息信息。然后通过监测这些日志信息你就可以很容易地发现系统中的问题了。10、总结Python 的日志库设计得如此之好真是让人欣慰我觉得这是标准库中最好的一部分了你不得不选择它。它很灵活你可以用你自己的 handler 或者 filter。已经有很多的第三方的 handler 了比如 pyzmq 提供的 ZeroMQ 日志句柄它允许你通过 zmq 套接字发送日志消息。如果你还不知道怎么正确的使用日志系统这篇文章将会非常有用。有了很好的日志记录实践你就能非常容易地发现系统中的问题。这是很非常值得投资的。:)日志模块使用总结 1、加载logging模块2、创建一个logger,并设置service用户记录日志logger logging.getLogger(service),使用%(name)s记录3、设置logger级别logger.setLevel(logging.DEBUG)4、创建一个handler日志流向文件或控制台默认是控制台# 创建一个handler用于写入日志文件fh logging.FileHandler(access.log)# 再创建一个handler用于输出到控制台ch logging.StreamHandler()5、# 定义handler的输出格式formatterformatter logging.Formatter(%(asctime)s - %(filename)s[line:%(lineno)d] - %(name)s - %(levelname)s - %(message)s)fh.setFormatter(formatter)ch.setFormatter(formatter)6、给logger添加handlerlogger.addHandler(fh)logger.addHandler(ch)7、记录一条日志logger.debug(logger debug message)logger.info(logger info message)logger.warning(logger warning message)logger.error(logger error message)logger.critical(logger critical message) 转载于:https://blog.51cto.com/xuanwei/1954983