Python写日志【自用】

记录代码出错的位置

def f2(b, a):
    print(b - a)

def f1(a, b):
    return f2(b, a)

def try_log(func, *args, **kwargs):
    from time import strftime
    from traceback import format_exc
    try:
        func(*args, **kwargs)
    except:
        error = format_exc()
        print('\033[031m', error, '\033[0m', sep='\n')
        with open('%s.log' % strftime('%Y-%m-%d'), 'a', encoding='utf-8') as f:
            f.write('%s\n' % error)

if __name__ == '__main__':
    try_log(f1, 1, b='2')

分日期保存文件

def write_log(*args):
    from time import strftime
    ymd = strftime('%Y%m%d')
    with open('%s.log' % ymd, 'a', encoding='utf-8') as f:
        for i in args:
            f.write('%r\n' % i)
        f.write('\n')

traceback+写文件

import os
from traceback import format_exc
from time import strftime
_path = os.path.dirname(__file__)
_get_abs_path = lambda path: os.path.normpath(os.path.join(_path, path))

def write_log(*args, **kwargs):
    fname = kwargs.pop('fname') if 'fname' in kwargs else'log.txt'
    with open(fname, 'a', encoding='utf-8') as f:
        for i in args:
            f.write('{}\n'.format(i))
            print('\033[031m', i, '\033[0m')
        for i in kwargs.items():
            f.write('{} {}\n'.format(*i))
            print('\033[031m', *i, '\033[0m')
        f.write('\n')

def traceback_func(func, *args, **kwargs):
    try:
        value = func(*args, **kwargs)
        return value
    except:
        error = format_exc()  # 在线程中失效
        write_log(error, *args, **kwargs)

def remove():
    """清空日志,谨慎启动"""
    for fname in os.listdir(_path):
        if '.txt' in fname:
            abs_fname = _get_abs_path(fname)
            print(abs_fname)
            os.remove(abs_fname)

if __name__ == '__main__':
    remove()

traceback+装饰器

from traceback import format_exc

def write_log(*args, **kwargs):
    fname = kwargs.pop('fname') if 'fname' in kwargs else'log.txt'
    with open(fname, 'a', encoding='utf-8') as f:
        for i in args:
            f.write('{}\n'.format(i))
            print('\033[031m', i, '\033[0m')
        for i in kwargs.items():
            f.write('{} {}\n'.format(*i))
            print('\033[031m', *i, '\033[0m')
        f.write('\n')

def traceback_func(fn):
    def function_timer(*args, **kwargs):
        try:
            result = fn(*args, **kwargs)
            return result
        except:
            error = format_exc().strip()  # 在线程中失效
            write_log(error, *args, **kwargs)
    return function_timer

def f1(a):
    print(int(a))

@traceback_func
def f2(a, *args, **kwargs):
    f1(a)

if __name__ == '__main__':
    f2('a', fname='a.txt', k='v')

logging模块

format中文解释remark
%(message)s日志信息必要
%(asctime)s时间常用
%(pathname)s绝对路径:sys.argv[0]常用
%(lineno)d行号常用
%(funcName)s函数名常用
%(module)s模块名有用
%(filename)s文件名有用
%(relativeCreated)d导入logging后的相对时间(毫秒级)有用
%(created)f当前时间:time.time()少用
%(levelname)s日志级别名称,DEBUG、INFO、ERROR……少用
%(levelno)s日志级别(10, 20, 30, 40, 50)少用
%(name)s日志器名称,默认root少用
%(process)s进程ID不用
%(processName)s进程名称不用
%(thread)s线程ID不用
%(thread)s线程名称不用
%(msecs)dasctime时间的毫秒部分不用
"""
message | %(message)s | 日志信息 | 必要
asctime | %(asctime)s | 时间 | 常用
pathname | %(pathname)s | 绝对路径:sys.argv[0] | 常用
lineno | %(lineno)d | 行号 | 常用
funcName | %(funcName)s | 函数名 | 常用
module | %(module)s | 模块名 | 有用
filename | %(filename)s | 文件名 | 有用
relativeCreated | %(relativeCreated)d | 导入logging后的相对时间(毫秒级) |有用
created | %(created)f | 当前时间:time.time() | 少用
levelname | %(levelname)s | 日志级别名称,DEBUG、INFO、ERROR…… | 少用
levelno | %(levelno)s | 日志级别(10, 20, 30, 40, 50) | 少用
name | %(name)s | 日志器名称,默认root | 少用
process | %(process)s | 进程ID | 不用
processName | %(processName)s | 进程名称 | 不用
thread | %(thread)s | 线程ID | 不用
threadName | %(thread)s | 线程名称 | 不用
msecs | %(msecs)d | asctime时间的毫秒部分 | 不用
"""
import logging, time
logging.basicConfig(level=logging.DEBUG, format=__doc__)  # 配置
# logging.info('msg')
time.sleep(.5)  # 检验relativeCreated
logger = logging.getLogger('a1')
logger.debug('msg')

打印结果

message | msg | 日志信息 | 必要
asctime | 2020-02-13 16:21:34,550 | 时间 | 常用
pathname | E:/PycharmProjects/anaconda/logger/__init__.py | 绝对路径:sys.argv[0] | 常用
lineno | 25 | 行号 | 常用
funcName | <module> | 函数名 | 常用
module | __init__ | 模块名 | 有用
filename | __init__.py | 文件名 | 有用
relativeCreated | 501 | 导入logging后的相对时间(毫秒级) |有用
created | 1581582094.550740 | 当前时间:time.time() | 少用
levelname | DEBUG | 日志级别名称,DEBUG、INFO、ERROR…… | 少用
levelno | 10 | 日志级别(10, 20, 30, 40, 50| 少用
name | a1 | 日志器名称,默认root | 少用
process | 4608 | 进程ID | 不用
processName | MainProcess | 进程名称 | 不用
thread | 14292 | 线程ID | 不用
threadName | 14292 | 线程名称 | 不用
msecs | 550 | asctime时间的毫秒部分 | 不用

路径引用示例

日志等级

日志级别名称描述日志级别
DEBUG调试,最详细的日志信息10
INFO基本信息(如,打印时间、进度、中间结果、最终结果…)20
WARNING预警信息(如,磁盘可用空间较低),此时应用程序仍正常运行30
ERROR错误信息,程序某功能不能运行40
CRITICAL严重错误信息,程序不能运行50
  • CRITICAL > ERROR > WARNING > INFO > DEBUG
  • 默认级别为WARNING(输出大于等于WARNING级别的日志)

四大组件

组件名称对应类名功能描述
日志器Logger提供了应用程序可一直使用的接口
处理器Handler将logger创建的日志记录发送到合适的目的输出
过滤器Filter提供了更细粒度的控制工具来决定输出哪条日志,丢弃哪条日志
格式器Formatter决定日志记录的最终输出格式
常用Logger方法
Logger.addHandler()
常用Handler
logging.StreamHandler:日志打印
logging.FileHandler:日志写入文件
常用Formater参数
fmt:格式
datefmt:时间格式

写文件

import logging

# logger对象
logger = logging.getLogger()

# Handler加入
sh = logging.StreamHandler()  # 打印
fh = logging.FileHandler('log.txt', encoding='utf-8')  # 写文件
logger.addHandler(sh)
logger.addHandler(fh)

# 日志等级
logger.setLevel(logging.DEBUG)
sh.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)

# 日志格式
fmt = logging.Formatter('%(message)s\n%(asctime)s\n%(pathname)s\n%(lineno)d\n')
sh.setFormatter(fmt)
fh.setFormatter(fmt)

# 日志过滤
class Filter(logging.Filter):
    def filter(self, record):
        if record.msg is not None:
            return True
logger.addFilter(Filter())

if __name__ == '__main__':
    logger.info('info')  # 只打印
    logger.warning('警告')  # 既打印也写文件
    logger.error(None)  # 过滤空值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小基基o_O

您的鼓励是我创作的巨大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值