python的树状日志记录实用工具
pytreelog的Python项目详细描述
pytreelog:python的类似树的日志工具
此工具允许python用户在层块中记录条目,这些块显示在树中,类似于结构:
-start
.-----------------------
|* f(x="test")
| -x = test
| .-----------------------
| :* Start loop:
| : -i=0
| : -i=1
| : -i=2
| :* end loop
| '-----------------------
'-----------------------
-done
功能:
- 在tree中显示类似于结构的python日志记录项;
- 输出可以显示在控制台中,也可以保存到变量或文件中
注意:这个README.md
文件既是一个doc,也是doc test的源(有关详细信息,请参阅test部分)。
安装
简单地
pip install pytreelog
或者最新的版本:
pip install git+https://gitlab.com/runsun/pytreelog.git
或者,如果你不想有这个医生也不想做测试,你可以简单地
将文件pytreelog/pytreelog.py
复制到任何需要的位置。
快速预览
frompytreelog.pytreelogimportTreeLogtl=TreeLog()tl(x)# log x2blocktypes:*userblock*and*funcblock*(See`DecoratorApproach`below).tl.b(x)# Beging a new *user block*. 'x' is optional. If not given, # x will be assigned the function call arg values. tl.e(x)# End the current block. 'x' is optional. If x not given# for a function that return something, it will show the# returned valuetl.data# list of lines of the logged datatl.text()# returns the data as a stringtl.reset()# reset the data and block info to start anew
打开/关闭
您可以使用以下任一选项打开/关闭登录:
tl.on()tl.off()
或
tl._on=Truetl._on=False
默认:打开
基本用法
>>> from pytreelog.pytreelog import TreeLog
>>> tl = TreeLog()
>>> def f(x):
... tl.b('BEG') ## <== New block
... tl("test line "+str(x)) ## <== Any string
... tl.e('END') ## <== End of a block
>>> f(1)
>>> print(tl.text()) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|* BEG
| -test line 1
|* END
'-----------------------
块的开始/结束:tl.b()
,tl.e()
>>> def f(x):
... tl.b()
... tl("test line "+str(x))
... tl.e()
>>> f(2)
>>> print(tl.text()) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|* BEG
| -test line 1
|* END
'-----------------------
.-----------------------
|* f(x=2)
| -test line 2
'-----------------------
注意:tl.b()
记录函数名和输入值,tl.e()
不记录任何内容。还要注意,输出将附加到以前的结果。
另一个例子:
>>> tl.reset()
>>> tl('start test') ## log a single line
>>> def f(x):
... a=0
... tl.b() ## Begin a block, logs func name and input value(s)
... tl('x = '+str(x)) ## Log a line
... tl.b('Starting loop:') ## Begin of another block
...
... for i in range(3):
... tl('i='+str(i)) ## Log i
...
... tl.e('end loop') ## End of block
... tl.e() ## End of block
>>> f('test')
>>> tl('done')
>>> print(tl.text()) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
-start test
.-----------------------
|* f(x="test")
| -x = test
| .-----------------------
| :* Starting loop:
| : -i=0
| : -i=1
| : -i=2
| :* end loop
| '-----------------------
'-----------------------
-done
装饰方法
下面显示功能块的日志记录方法:
defff():tl.b()...tl.e()可以在使用装饰器的实例中,使用装饰器的实例,在装饰器中跟踪函数的入口/出口,例如:
@tldefff():...
这允许:
- 记录函数的返回值:
日志函数返回
decorator方法自动记录函数的返回:
>>> tl.reset()
>>> @tl
... def test(a,b=0):
... tl.b('User-block beg')
... tl('Inside test()')
... tl.e('User-block end')
... return a+b
>>> test(3,4)
7
>>> print(tl.text()) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|> test(a=3, b=4)
| .-----------------------
| :* User-block beg
| : -Inside test()
| :* User-block end
| '-----------------------
|< 7
'-----------------------
注意,使用decorator arrpoach,function block head/tail(即>
和<
)的符号不同于使用tl.b()
和tl.e()
(即*
)登录的符号。这允许日志将功能块和用户定义块分开:
- 功能块:
>
和<
- 用户定义块:
*
和*
两者都可以定制(请参见下面的customizeable api)。
一次性使用的装饰方法
如果只想跟踪函数的输入/退出,则使用未绑定实例一次性使用:
>>>@TreeLog()...deftest3():......
更多示例:
>>> tl.reset()
>>> @tl
... def test(a,b=0):
... tl.l('Inside test()')
... @tl
... def inside(a,b):
... return a+b
... return inside(a,b)*2
>>> test(3,4)
14
>>> print(tl.text()) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|> test(a=3, b=4)
| -Inside test()
| .-----------------------
| :> a.inside(b=4)
| :< 7
| '-----------------------
|< 14
'-----------------------
在类中使用decorator方法
在类中使用TreeLog
的示例:
>>> log= TreeLog()
>>> class Cls(object):
... @log
... def __init__(self):
... self.clsname = 'CLS'
... self.setname( prefix='I am ') ## run inside __init__
... @log
... def setname(self, prefix):
... self.name= prefix + self.clsname
... @log
... def getname(self):
... return self.name
>>> cc = Cls() ## run __init__, logging __init__ and setname.
>>> cc.getname()
'I am CLS'
>>> cc.setname('This is ') ## run outside __init__.
## Note the user arg ('This is ') is logged.
>>> cc.getname()
'This is CLS'
>>> print(BR.join( log.data )) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|> self.__init__()
| .-----------------------
| :> self.setname(prefix="I am ")
| '-----------------------
'-----------------------
.-----------------------
|> cc.getname()
|< "I am CLS"
'-----------------------
.-----------------------
|> cc.setname(prefix="This is ")
'-----------------------
.-----------------------
|> cc.getname()
|< "This is CLS"
'-----------------------
请注意:
- 已记录实例名cc;
- setname被记录两次,一次绑定到self,另一次绑定到cc。
- getname有一个返回,它也被记录下来。
输出
tl.data
是包含记录的字符串的列表。tl.text()
返回单个字符串。
您也可以登录到外部变量/文件:
记录到外部变量
使用external
参数将输出保存到变量,该变量
dict包含一个data
键,{'data':[]}
:
>>> external={'data':[]}
>>> p = TreeLog(external=external)
>>> p.b('start')
>>> @p
... def g(name):
... p.l('test')
>>> g('g')
>>> p.e('stop')
>>> for x in external['data']: print(x) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
|* start
| .-----------------------
| :> g(name="g")
| : -test
| '-----------------------
|* stop
'-----------------------
登录到文件
您可以登录到文件:
pp=TreeLog(logfile='./pytreelog.log')
可定制的API
TreeLog()
模块的默认值:
TreeLog(header='='*45+BR+'TreeLog output'+BR+'='*45,_on=True,block_beg='* ',block_end='* ',func_beg='> ',func_end='< ',indent=1,blockline='-----------------------',blocksymbols='|:',external=None# External var ( {'data':[]} ) to which the data is logged,logfile='')
blocksymbols
:包含所有层左边框符号的str。默认值是|:
,表示左边框的符号将是|
和:
。
以下示例显示3的可选符号(即[=!
):
>>> tl= TreeLog(blocksymbols= '[=!')
>>> @tl
... def f():
... tl.b('1st layer')
... for i in (1,2):
... tl.b('2nd layer')
... for j in (3,4):
... tl.b('3rd layer')
... for k in (5,6):
... tl( str( (i,j,k) ) )
... tl.e()
... tl.e()
... tl.e()
>>> f()
>>> print(BR.join( tl.data )) # doctest: +NORMALIZE_WHITESPACE
=============================================
TreeLog output
=============================================
.-----------------------
[> f()
[ .-----------------------
[ =* 1st layer
[ = .-----------------------
[ = !* 2nd layer
[ = ! .-----------------------
[ = ! [* 3rd layer
[ = ! [ -(1, 3, 5)
[ = ! [ -(1, 3, 6)
[ = ! '-----------------------
[ = ! .-----------------------
[ = ! [* 3rd layer
[ = ! [ -(1, 4, 5)
[ = ! [ -(1, 4, 6)
[ = ! '-----------------------
[ = '-----------------------
[ = .-----------------------
[ = !* 2nd layer
[ = ! .-----------------------
[ = ! [* 3rd layer
[ = ! [ -(2, 3, 5)
[ = ! [ -(2, 3, 6)
[ = ! '-----------------------
[ = ! .-----------------------
[ = ! [* 3rd layer
[ = ! [ -(2, 4, 5)
[ = ! [ -(2, 4, 6)
[ = ! '-----------------------
[ = '-----------------------
[ '-----------------------
'-----------------------
测试
所有测试都写在这个README.md
中(这意味着,这个README.md
既是一个文档又是测试)。此文件的内容由pytreelog.test()
加载并分配给TreeLog.__doc__
,然后由doctest.testmod()
执行测试(有关详细信息,请参阅pytreelog.test()
中的代码)。
\>>>frompytreelogimportpytreelog \>>>pytreelog.test()---Loading"C:\python37\lib\site-packages\pytreelog\README.md"fordoctest:---Testsdone.