Skip to content

日志处理

日志可以使用内置的logging模块来生成
服务端的日志可以使用内置的sqlite3模块来持久化。

logging 模块

python
import logging

##级别依次提高
logging.debug("排错信息")
logging.info("正常信息")
logging.warning("警告信息")
logging.error("错误信息")
logging.critical("严重错误信息")

默认情况下 Python 的 logging 模块将日志打印到了标准输出(sys.stdout)中,
且只显示了大于等于 WARNING 级别的日志

默认的日志格式为 日志级别:Logger名称:用户输出消息

它有两种配置方法

  • 配置 logging 全局参数
  • 显式地创建 logger 实例并配置

也可以同时在两处配置,logger 实例上的配置优先级更高。

配置 logging 全局参数

basicConfig()函数更改 logging 模块默认行为

  • 缺点:低版本 python 里中文会乱码,不能同时控制台打印和写入文件
  • 优点:灵活配置日志级别,日志格式,和输出位置

简单的配置:

python
import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s",
    datefmt="%a, %d %b %Y %H:%M:%S",
    filename="/tmp/test.log",
    filemode="w",
)

logging.debug("debug message")
logging.info("info message")
logging.warning("warning message")
logging.error("error message")
logging.critical("critical message")

更多的配置选项

  • filename:用指定的文件名创建 FiledHandler,这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了 filename 时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定 handler 使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置 rootlogger 的日志级别
  • stream:创建指定的 StreamHandler。默认 sys.stderr 可选 sys.stdout 或者文件句柄

若指定了filename,则stream参数会被忽略。

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用户输出的消息

配置 logger 实例参数

logging.getLogger()实例化一个记录器对象

即使不实例化,也会默认创建root logger,缺省值读取basicConfig()的配置
记录器对象可以设置:

  • logger.setLevel(logging.ERROR) 设置日志级别为 ERROR
  • logger.addHandler(handler_name) 为 Logger 实例增加一个处理器
  • logger.removeHandler(handler_name) 为 Logger 实例删除一个处理器

创建和添加处理器 Handler

python
import logging

logger = logging.getLogger()
# 用于写入日志文件的handler
fh = logging.FileHandler("test.log", encoding="utf-8")
# 用于输出到控制台的handler
ch = logging.StreamHandler()
# logger对象可以添加多个handler
logger.addHandler(fh)
logger.addHandler(ch)

处理器对象也可以设置:

  • ch.setLevel(logging.WARN) # 单对这个流设置日志级别
  • ch.setFormatter(formatter_name) # 设置一个格式化器 formatter
  • ch.addFilter(filter_name) # 增加一个过滤器,可以增加多个
  • ch.removeFilter(filter_name) # 删除一个过滤器

创建格式化器:

python
fh = logging.FileHandler("test.log", encoding="utf-8")
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
fh.setFormatter(formatter)
logger.addHandler(fh)

sqlite3 模块

SQLite 是一种文件数据库,它的数据库就是一个文件。Python 内置了 SQLite3。它适合作为保存日志的数据库。谷歌浏览器的 cookie 也使用了它。

基本用法示例

shell
>>> import sqlite3

# 创建连接,如果文件不存在,会自动在当前目录创建:
>>> conn = sqlite3.connect('test.db')

# 创建游标
>>> cursor = conn.cursor()

# 执行SQL语句,创建user表:
>>> cursor.execute(r"""CREATE TABLE "user" (
        "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
        "name" varchar(20)
    );""")
<sqlite3.Cursor object at 0x10f8aa260>

# 继续执行一条SQL语句,插入一条记录:
>>> cursor.execute(r"""INSERT INTO "main"."user"(name) VALUES ('Michael');""")
<sqlite3.Cursor object at 0x10f8aa260>

# 关闭游标
>>> cursor.close()

# 提交事务
>>> conn.commit()

# 关闭连接
>>> conn.close()

游标对象常用属性和方法

  • cursor.execute()执行 SQL 语句并返回cursor对象本身
  • cursor.rowcount刚刚执行语句影响的行数
  • cursor.fetchone()弹出刚刚执行查询语句的结果集的第一条,元组
  • cursor.fetchall()刚刚执行查询语句的全部(剩余)结果集,列表嵌套元组

直接遍历(for in)cursor对象本身也可以拿到(剩余)结果集

sqlite 方言和一般的 sql 略有区别,比如单引号和双引号的区别,没有实现 truncate 语句等。

基本的 sql 语句和更多的数据库连接模块的用法在之后章节有介绍。