Log日志

Log日志

1 Logging

日志是对程序执行过程中进行事件的记录追踪方式  

1.1 logging输出配置

basicConfig()  # 基础配置
fileConfig()  # 通过读取配置文件配置
dictConfig()  # 通过字典配置logger handler filter等
listen()  # 通过监听网络端口 接收配置文件数据进行配置

1.2 配置实例-basicConfig

# Pyhton内置模块logging使用
import logging
Log_Level='日志等级'
Log_Format = '日志输出格式'
File_Name = '日志保存的文件名'
File_Mode = '日志打开|写入方式'  # 没有filemode 默认为追加
Date_fmt = '自定义输出的日期格式'
# 日志配置信息
logging.basicConfig(level=Log_Level, 
                    format=Log_Format, 
                    filename=File_Name,
                    filemode=File_Mode,
                    datefmt=Date_fmt,
                   )
# basicConfig其他可选参数
# stream:相当于创建StreamHandler 指定控制台输出 与 filename冲突
# filename:相当于创建FileHandler 指定文本输出 
level参数	
日志输出等级 >= 配置的等级
    - DEBUG:程序运行的详细信息 每次请求 每个操作都会记录
    - INFO:日常程序运行正常信息
    - WARNING:警告信息-程序|程序功能不受影响
    - ERROR:严重错误-程序部分功能失效
    - CRITICAL:严重问题-程序崩溃
format参数
规范日志输出的具体内容
    %(levelno)s: 输出日志级别数值
    %(levelname)s: 输出日志级别名称
    %(pathname)s: 输出执行程序的路径
    %(filename)s:输出执行程序的文件名称
    %(funcName)s:输出日志的当前函数
    %(lineno)d:输出日志的行号
    %(asctime)s:输出日志的时间
    %(thread)d:输出线程id
    %(threadName)s: 输出线程名称
    %(process)d: 输出进程id
    %(message)s: 输出日志信息
datefmt参数
datefmt = '%Y/%m/%d %I:%M:%S %p'  # 2020/12/22 11:46:36 AM

1.3 Logger

Logger 日志器:暴露程序的使用的接口信息 即产生一个关联程序的日志接口
	-创建:logger_obj = logging.getLogger(name='logger_name')  默认名root
	-设置总的log输出等级:logger_obj.setLevel(logging.INFO)
	-关联Handler处理器指定输出: logger_obj.addHandler(handler_name)
	-关联Filter:logger_obj.addFilter(filter_name)

1.4 Handler

Handler 处理器:处理logger产生的日志记录到指定的位置
	StreamHandler  # 控制台日志输出
		-创建: sh = logging.StreamHandler(stream=None)  默认stream=sys.stdout
		-设置日志输出等级:sh.setLevel(logging.INFO)
		-设置日志输出格式:sh.setFormatter('Formatter_name')
		-设置日志输出的过滤规则: sh.addFilter('Filter_name')
	FileHandler  # 文本输出
		-创建:logging.FileHandler(filename='日志文件名', mode='写入模式', encoding='编码模式')
		
	RotatingFileHandler  # 支持磁盘文件回滚输出
		-创建: logging.handlers.RotatingFileHandler(filename='',
                                     mode='',
                                     maxBytes=0,
                                     backupCount=0)
         # maxBytes:决定日志文件的长度 设置maxBytes&&backupCount >0 可实现回滚
         # backupCount:决定备份的文件数
import logging.handlers

logger = logging.getLogger()

rh = logging.handlers.RotatingFileHandler(filename='./test.log',
                                     mode='a',
                                     maxBytes=10,
                                     backupCount=3,
                                     encoding=None,
                                     delay=0)
rh.setLevel(level=logging.ERROR)
rh.setFormatter(logging.Formatter("%(name)s:%(asctime)s-%(levelname)s-%(message)s"))
logger.addHandler(rh)


# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


1.5 Formatter

Formatter 格式化器: 输出特定格式的日志信息
	-创建: f = logging.Formatter(fmt='', datefmt='', style='')  
	-fmt 默认消息格式化字符串->%(message)s
	-datefmt 默认日期格式化字符串->'%Y-%m-%d %H:%M:%S'
	-style 默认取值'%'格式 可选{ | $

1.6 Filter

Filter 过滤器: 过滤输出特定的日志信息
	-创建:
	class MyFilter(logging.Filter):
    	def filter(self, record):
    		print('record', 'LogRecord')
    		# 每个日志信息都保存在LogRecord实例
    		pass
	-关联:与logger全局关联 通过过滤规则完成日志输出 | 与logger下handler局部关联
	-logger_obj.addFilter(MyFilter())
	-handler_obj.addFilter(MyFilter())

1.7 日志输出 -basciConfig

1.7.1 控制台输出

# 控制台输出(默认)-stream
import logging

Log_Level = logging.INFO
Log_Format = '%(asctime)s-{%(process)d-[%(threadName)s:%(thread)d]} %(pathname)s-%(filename)s[line:%(lineno)d]--->%(funcName)s- %(levelname)s - %(message)s'
Date_fmt = '%Y/%m/%d %I:%M:%S %p'
logging.basicConfig(level=Log_Level,
                    format=Log_Format,
                    datefmt=Date_fmt,
                    )
    
# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


1.7.2 文本输出

# 提供filename参数
import logging

Log_Level = logging.INFO
Log_Format = '%(asctime)s-{%(process)d-[%(threadName)s:%(thread)d]} %(pathname)s-%(filename)s[line:%(lineno)d]--->%(funcName)s- %(levelname)s - %(message)s'
File_Name = './log1.log'
File_Mode = 'w'  # 没有filemode 默认为追加a
logging.basicConfig(level=Log_Level,
                    format=Log_Format,
                    filename=File_Name,
                    filemode=File_Mode,
                    Date_fmt = '%Y/%m/%d %I:%M:%S %p',
                    )
# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')



1.7.3 控制台+文本 输出

import logging

# 显式创建logger记录器(默认会创建一个root logger并引用默认日志等级warn)
import sys

logger = logging.getLogger()
logger.setLevel(logging.INFO)  # 记录器记录的Log等级

# 创建FileHandler 指定日志信息输出到日志文件
logfile = './log1.log'
fh = logging.FileHandler(logfile, mode='w')
fh.setLevel(logging.DEBUG)  # 设置输出到文本的log等级

# 创建StreamHandler 指定日志信息输出到控制台
kh = logging.StreamHandler(stream=sys.stdout)
kh.setLevel(logging.WARNING)   # 设置输出到控制台的log等级

# 创建Formatter 统一输出格式
_formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")

# 设置handler输出格式
fh.setFormatter(_formatter)
kh.setFormatter(_formatter)


# 创建Filter 过滤输出需要的日志信息
class MyFilter(logging.Filter):
    def filter(self, record):
        # 过滤输出指定日志等级 warn error
        # record:为日志信息
        if record.__dict__.get('levelname') in ['WARNING', 'ERROR']:
            return True
        else:
            return False
        

# handler关联filter(局部控制输出的log日志等级信息)
# kh.addFilter(MyFilter())

# logger关联handler
logger.addHandler(fh)
logger.addHandler(kh)

# # logger关联过滤器(全局控制输出log日志等级)
# logger.addFilter(MyFilter())
    
    
# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


1.8 日志输出-fileConfig

# logconfig.conf
[loggers]
keys=root
# default:root-logger
[handlers]
keys= kh, fh

[formatters]
keys=FhFormatter, KhFormatter

# logger-setting_detail
[logger_root]
level=INFO
handlers= kh, fh

#kh_handler_setting
[handler_kh]
class = StreamHandler
level = WARNING
formatter = KhFormatter
args=()

# fh_handler_setting
[handler_fh]
class = FileHandler
level = DEBUG
formatter = FhFormatter
args=('./log3.log', 'w')

# formatter_setting
[formatter_FhFormatter]
format=%(name)s:%(asctime)s - %(levelname)s - %(message)s
datefmt = %Y/%m/%d %H:%M:%S

[formatter_KhFormatter]
format=%(name)s:%(asctime)s - %(levelname)s - %(message)s
import logging.config

# 通过配置文件logconfig.conf控制日志输出 
# xx.conf配置文件不能出现中文 否则报错gbk
logging.config.fileConfig('logconfig.conf')

# 创建默认名root的logger
logger = logging.getLogger()


# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


1.9 日志输出-dictConfig

1.9.1 dictConfig: dict

import logging.config

# logging配置信息 可以是dict | json | yaml
config_dict = {
        'version': 1,
        'formatters': {
            'FhFormat': {
                'class': 'logging.Formatter',
                'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s'
            },
            'ChFormat': {
                'class': 'logging.Formatter',
                'format': '%(asctime)s-%(levelname)s-%(message)s'
            }
        },
    
        'handlers': {
            'ch': {
                'class': 'logging.StreamHandler',
                'level': 'INFO',
                'formatter': 'ChFormat'
            },
            'fh': {
                'class': 'logging.FileHandler',
                'level': 'WARNING',
                'filename': './log4.log',
                'mode': 'w',
                'formatter': 'FhFormat',
            },
        },
        #  可指定多个logger
        # 'loggers': {
        #     'foo': {
        #         'handlers': ['foofile']
        #     }
        # },
            'root': {
                'level': 'DEBUG',
                'handlers': ['ch', 'fh', ]
            },
        }

# 通过字典配置logging输出
logging.config.dictConfig(config_dict)


# 测试数据
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')


1.9.2 dictConfig: json

{
  "version": 1,
  "formatters": {
    "FhFormat": {
      "class": "logging.Formatter",
      "format": "%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s"
    },
    "ChFormat": {
      "class": "logging.Formatter",
      "format": "%(asctime)s-%(levelname)s-%(message)s"
    }
  },
  "handlers": {
    "ch": {
      "class": "logging.StreamHandler",
      "level": "INFO",
      "formatter": "ChFormat"
    },
    "fh": {
      "class": "logging.FileHandler",
      "level": "WARNING",
      "filename": "./log4.log",
      "mode": "w",
      "formatter": "FhFormat"
    }
  },
  "root": {
    "level": "DEBUG",
    "handlers": [
      "ch",
      "fh"
    ]
  }
}
# 通过xx.json文件进行配置logging日志输出
with open(xx.json, 'r') as f
	_config = json.load(f)

logging.config.dictConfig(_config)

1.9.3 dictConfig:yaml

version: 1
formatters:
  FhFormat:
    class: logging.Formatter
    format: "%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s"
  ChFormat:
    class: logging.Formatter
    format: "%(asctime)s-%(levelname)s-%(message)s"

handlers:
  ch:
    class: logging.StreamHandler
    level: INFO
    formatter: ChFormat
  fh:
    class: logging.FileHandler
    level: WARNING
    filename: ./log4.log
    mode: w
    formatter: FhFormat

root:
  level: DEBUG
  handlers: [ch, fh]
# 通过ymal文件进行日志文件输出配置(pip install pyyaml)
with open('logconfig.yaml', 'r') as f:
    _config = yaml.load(f, Loader=yaml.SafeLoader)
logging.config.dictConfig(_config)

1.10 日志输出-listen()

# 相当于服务端日志平台 通过监听端口 接收特定配置文件更改logging日志输出配置
import logging.config, logging.handlers
import time

# 通过监听特定端口加载logging配置信息
t = logging.config.listen(8888)
print(t.name, t.port)
t.start()

# 创建默认的logger
logger = logging.getLogger()

try:
    while True:
        # 测试数据刷新
        logging.debug('debug message')
        logging.info('info message')
        logging.warning('warning message')
        logging.error('error message')
        logging.critical('critical message')
        time.sleep(5)
        print('='*50)
except:
    # 停止监听
    logging.config.stopListening()
    t.join()
# 发送方 发送特定配置文件给服务端实质是tcp连接
# 这里引用上面的logconfig.conf配置文件
import socket, sys, struct

try:
    with open(sys.argv[1], 'rb') as f:
        data_to_send = f.read()
except:
    print('缺少执行参数请使用: python xx.py  xx.conf')

# 连接的服务端ip:port
HOST = 'localhost'
PORT = 8888

# 创建tcp套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('connecting...')
# 连接
s.connect((HOST, PORT))
print('sending config...')
# 发送二进制的配置文件内容
s.send(struct.pack('>L', len(data_to_send)))
s.send(data_to_send)
# 关闭套接字
s.close()
print('complete')



2 Traceback

2.1 traceback

Traceback模块
追踪输出完成的异常信息
	-异常出现的代码行
	-详细的异常类型
	-异常信息输出详细|简略
	
实质是通过traceback_obj对象获取异常信息  
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_tb(exc_traceback_ojb) 

pip install traceback  # 安装模块

2.2 traceback实例

import sys
import traceback


def test():
    raise Exception('异常信息')

try:
    test()
except Exception as e:
    print(sys.exc_info())
    print('-'*100)
    exc_type, exc_val, exc_traceback_obj = sys.exc_info()
    print(exc_type, exc_val, exc_traceback_obj)
    print('-' * 100)
    traceback.print_tb(exc_traceback_obj)
    print('-' * 100)
    traceback.print_exception(exc_type, exc_val, exc_traceback_obj, limit=2, file=sys.stdout)
    print('-' * 100)
    traceback.print_exc(limit=1, file=sys.stdout)


2.3 logging + traceback

traceback.format_exc() :字符串形式输出异常信息
traceback.print_exc(): 打印输出异常信息
traceback.print_exc(file=open('error.log', 'a'))  # 异常信息存储到指定文件

2.4 logging+traceback实例

import logging
import traceback


logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s -%(levelname)s -%(message)s',
                    filename='./log2.log',
                    filemode='w')

try:
    res = 5/0
    logging.info('info:res-success')
except:
    # 打印异常信息详情
    traceback.print_exc()
    # 格式化异常信息打印输出到日志
    logging.error(f'error: {str(traceback.format_exc())}')



3 flask + logging+ traceback

import logging
import traceback
from flask import Flask
from flask_restful import Api, Resource, fields

app = Flask(__name__)
api = Api(app)


class Test(Resource):
    def get(self):
        res = 5/0
        return {'name': 'fsh', 'job': 'python trainee'}
      
        
# 路由配置
def route_init():
    api.add_resource(Test, '/')
    

# 日志处理
Log_format = '%(asctime)s - %(levelname)s - %(message)s'
logging.basicConfig(filename='./flask.log', level=logging.INFO, format=Log_format)
try:
    route_init()
except Exception as e:
    logging.info('find-error')
    logging.exception(f'error:{str(e)}')
    logging.exception(f'traceback:{str(traceback.format_exc())}')


if __name__ == '__main__':
    app.run()



4 gunicorn+flask+ logging

gunicorn 全名green unicorn  高并发的Python WSGI Unix Http服务器 
pip install gunicorn
# gunicorn-conf.py
# 添加logs目录
from multiprocessing import cpu_count

workers = (cpu_count() * 2 + 1) if cpu_count() < 10 else 20  # 开启的进程数
worker_class = 'eventlet'  # 工作模式默认同步(sync) |(异步:gevent/eventlet)
threads  = 2  # 设置每个进程的线程数
loglevel = 'info'  # 设置日志等级与accesslog相关
bind = 'localhost:9999'  # 监听的ip:port
pidfile = 'logs/gunicorn.pid' # 进程号保存路径
accesslog = 'logs/access.log'  # 请求日志
errorlog = 'logs/error.log'  # 运行产生的具体日志信息
from flask import Flask

app = Flask(__name__)


@app.route('/')
def test():
    return {"a": 'test_data'}


if __name__ == '__main__':
    app.run()

# terminal
# 第一个app:flask实例所在文件; 第二个app:flask实例名
# 通过配置文件启动gunicorn
gunicorn -c gunicorn-conf.py app:app 



5 帮助文档

[1] logging官方文档 https://docs.python.org/zh-cn/3/howto/logging.html

[2] logging config https://docs.python.org/zh-cn/2/library/logging.config.html

posted @ 2020-12-23 15:54  爱编程_喵  阅读(666)  评论(0)    收藏  举报
jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.