lk-logger
是一个增强型的打印库, 它被设计为能直接替换 python 内置的 print
函数, 在此之上提供两个对开发者更友好的功能:
- 在打印内容时, 同时打印出源码所在文件行号
- 通过一些预设的标记, 打印具有高亮效果或特定格式的文本
下面的两张图直观地说明 print
和 lk-logger
的打印效果区别:
安装和使用
通过 pip 安装, 支持 python 3.8 及以上版本:
pip install lk-logger
使用方法很简单, 在主入口文件添加下面两行代码, 则全部脚本都会生效:
python"># main.py# add two lines to import & setup lk-logger
import lk_logger
lk_logger.setup()# now it effects
print('hello world')
# ./main.py:8 > hello world
以上, 几乎就是 lk-logger 的全部用法.
更多用法
显示变量名
import lk_logger
lk_logger.setup(show_varnames=True)
# ^^^^^^^^^^^^^^^^^^
a = 1
b = 2
print(a, b, a + b)
设置 setup
函数传参 show_varnames=True
, lk-logger
会检测源代码中的变量名, 伴随值一同打印出来:
它的效果类似于 print(f'a = {}; b = {}; a + b = {}'.format(a, b, a + b))
, 但明显地书写要简洁得多.
美化来自第三方库的打印
假设导入的第三方库 (比如 “site-packages” 目录下的第三方包) 也用了 print
代码, lk-logger
会缩写源文件路径, 并以其他颜色高亮显示库名称:
import lk_logger
lk_logger.setup(quiet=True, show_varnames=True)import depsland # pip install depsland
# ^ there are some prints in depsland initial time.
# let's see the print results.
print(depsland.__version__)
高亮文本
下面是一部分常见的高亮效果示例, 完整的语法标记表在后面的 “标记语法” 一节给出.
import lk_logger
lk_logger.setup(quiet=True)print('[red]hello[/] [yellow]world[/]', ':r')
# ^ notice ':r' mark, we'll explain later.print(':d', 'divider line')# verbosities
print(':v0', 'debug')
print(':v1', 'info (dimmed)')
print(':v2', 'info')
print(':v3', 'success (dimmed)')
print(':v4', 'success')
print(':v5', 'warning (dimmed)')
print(':v6', 'warning')
print(':v7', 'error (dimmed)')
print(':v8', 'error')
异常处理
lk-logger
依赖 rich
库, 后者提供了漂亮的异常信息界面:
import lk_logger
lk_logger.setup(quiet=True)
# try to raise an error
x = 1 / 0
在 IPython 中使用
lk-logger
在 ipython 中对效果进行了一些调整, 减少了信息的干扰, 以适应 ipython 的使用场景.
该功能是自动的, 不需要在代码中额外添加参数.
计时和计数
这里会用到 “标记用法”, 关于标记语法会在后续章节详细说明, 下面仅作效果展示:
import lk_logger
lk_logger.setup(quiet=True)print(':d', 'indexing')
print(':i', 'aaa')
print(':i', 'bbb')
print(':i', 'ccc')
print(':i0', 'reset counter')
print(':i', 'ddd')
print(':i', 'eee')
print(':i', 'fff')print(':d', 'timing')
from time import sleep
sleep(0.1)
print(':t', '... in a short delay')
sleep(1)
print(':t', '... in a little long delay')
sleep(5)
print(':t', '... in a long delay')
进阶用法
反射源码层级
默认情况下, lk-logger
打印的是当前的源码所在的文件行号. 有时候我们会想打印源码的上一层级 (frame), 以便了解是谁在调用当前模块.
假设有一个函数叫 “借阅图书”, 当这个函数被调用时, 我们想知道是谁在借阅图书 (也就是打印借阅者所在的文件行号), 可以这样做:
import lk_logger
lk_logger.setup(quiet=True, show_varnames=True)def borrow_a_book(username: str, bookname: str) -> None:# use ':p' to point to the parent frameprint(username, bookname, ':p')borrow_a_book('Shawn', 'Python Crash Course')# after a while...borrow_a_book('Alice', 'Deep Learning With Python')
将打印输出到其他处理器 (实验性功能)
import atexit
import lk_logger
from lk_logger import parallel_printinglk_logger.setup(quiet=True)class MyLogger:def __init__(self):self._buffer = []atexit.register(self.close)def write(self, msg: str):self._buffer.append(msg)def close(self) -> None:with open('log.txt', 'w') as f:f.write('\n'.join(self._buffer))class MyGui:def update_ui(self, msg: str) -> None:""" send message to GUI log panel. """...mylogger = MyLogger()
mygui = MyGui()with parallel_printing(mylogger.write,mygui.update_ui,inherit=True, # default True. # ^ change to False to prevent default behavior (i.e. printing to console).
):print('hello world!')
标记语法
lk-logger
使用 “标记” 来简单快速地实现一些常用的高亮效果或文本格式化处理.
所谓的 “标记”, 是指位于 print
函数的第一个或最后一个参数位置的一个 str 类型的文本, 它以冒号开头, 后跟一个或多个字母和数字, 其形式如下:
python">print(':i', 'aaa')
print(':d', 'bbb')
print(':v2', 'ccc')
print(':v4t', 'ddd')
print('eee', ':i')
...
完整的标记符号表如下:
标记 | 助记词 | 说明 |
---|---|---|
:d | divider | 分割线 |
:e | exception | 异常信息格式化 |
:f | flush | 清空缓存的打印流 (在多线程打印中有效) |
:i | index | 计数器 |
:l | long | 长文本格式, 美化对象输出格式 |
:p | parent | 父层级反射 |
:r | rich | 富文本格式 (采用 bbcode 高亮语法) |
:s | short | 短文本格式 (减弱打印效果) |
:t | timer | 计时器 |
:v | verbosity | 打印等级 |
每个标记符号后面都可以跟一个数字, 数字范围 0 ~ 9. 如果不加数字, 则使用默认的数字, 如下表所示:
标记 | 说明 | 备注 |
---|---|---|
:d0 (默认) | 默认风格的分割线 (一条单横线) | |
:d1 | 块状风格的分割线 (多行文本) | 未实现 |
:e0 (默认) | 以 rich 风格美化异常信息 | |
:e1 | 在 :e0 基础上, 额外显示 locals 信息 | |
:e2 | 进入 pdb 交互式控制台 | 未实现 |
:f0 (默认) | 清空缓存的打印流, 将它们输出到控制台 | |
:f1 | 清空缓存的打印流, 但不输出到控制台 (会显示一个 “已跳过多少条待打印信息” 的提示) | |
:f2 | 无视缓存的打印流, 优先打印当前信息 (缓存不会被清空) | 未来可能移除此项 |
:i0 | 重置计数器 | |
:i1 (默认) | 智能计数, 会在合适的作用域开始计数和自动重置计数 | |
:i2 | 行计数器, 每次调用计数 +1 | |
:i3 | 全局计数器, 每次调用计数 +1 | |
:l0 (默认) | 长文本格式, 美化对象输出格式 | |
:l1 | 尽可能以可读的方式展示对象, 对一些 object 对象效果更好 | |
:p0 | 反射到自身层级 (也就是源码所在的文件行号) | |
:p1 (默认) | 反射到上一层级 | |
:p2 , :p3 , :p4 , … | 反射到上上一帧, 上上上一帧, … | 谨慎使用, 超过栈深度会报错 |
:r0 (默认) | 富文本风格 (采用 bbcode 高亮语法) | |
:r1 | 打印 rich 对象, 例如 rich.panel.Panel 实例 | |
:r2 | 以合适的 rich 风格打印对象, 目前仅支持符合特定格式的 str, dict, list | |
:s0 (默认) | 短文本格式 (减弱打印效果) | |
:s1 | 进一步减弱打印效果, 使其几乎与内置的 print 效果一致 | |
:s2 | 完全使用内置的 print 来处理打印 | |
:t0 | 重置计时器 | |
:t1 (默认) | 计时 (打印到当前为止的时间戳) | |
:t2 | 临时计时器, 局部计时器 | 待重构 |
:v0 (默认) | 调试信息 (灰色高亮) | |
:v1 | 负面提示信息 (紫色) | |
:v2 | 正面提示信息, 或无倾向的提示信息 (蓝色) | |
:v3 | 成功信息 (弱提醒) (暗绿色) | |
:v4 | 成功信息 (绿色) | |
:v5 | 弱警告 (暗黄色) | |
:v6 | 警告 (黄色) | |
:v7 | 报错 (弱提醒) (暗红色) | |
:v8 | 报错 (红色) | 助记: 2, 4, 6, 8 为主; 1, 3, 5, 7 为辅 |