初级
1. print 大法
print调试
2. log的debug级别调试
基础使用
import logging
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
oLogger = logging.getLogger(__name__)
oLogger.info("start script 123")
oLogger.debug("a = %s" % 1)
oLogger.warning("错误的id")
oLogger.error("异常情况")
oLogger.critical("十分严重")
日志级别
使用logger.setLevel(logging.INFO)方法就可以设置日志级别
INFO:会输出除了debug之外的所有信息 (个人理解,用于日常正式日志记录,这些日志需要永久保存的)
DEBUG: 会输出所有信息,包括INFO (个人理解,用于开发环境,需要详细的日志信息,这些日志是可以隔一段时间清楚的)
WARNNING:只会输出同级或者更高级的日志信息
ERROR:只会输出同级或者更高级的日志信息
CRITICAL:只会输出同级或者更高级的日志信息
记录到文件
动态配置
- 从logging拿到filehandler,
- 设置filehandler属性
- 从logging拿到logger,然后把handler给logger
def LogToFile():
# 设置文件handle
oHandle = logging.FileHandler("log/logging.txt")
oHandle.setLevel(logging.DEBUG)
oFormatter = logging.Formatter("[%(asctime)s - %(name)s - %(levelname)s - %(message)s]")
oHandle.setFormatter(oFormatter)
# 添加handle到oLog上
oLog = logging.getLogger(__name__)
oLog.addHandler(oHandle)
# 记录日志
oLog.info("start script 123")
oLog.debug("a = %s" % 1)
oLog.warning("错误的id")
oLog.error("异常情况")
oLog.critical("十分严重")
通过配置文件配置
有多种方式配置,这里使用json格式配置
json文件中内容:
{
"version":1,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
},
"handlers": {
"info_handler":{
"class": "logging.FileHandler",
"level": "INFO",
"formatter": "simple",
"filename": "info.log"
}
},
"loggers": {
"my_module": {
"level": "ERROR",
"handlers": ["info_handler"]
}
}
}
使用:
import json
import logging.config
PATH_LOG_CONF = r"D:\study\python\pycode\python_study\log\logging.json"
#从json中读取配置来记录日志
def LogFromJson():
with open(PATH_LOG_CONF) as f:
dConfig = json.load(f)
logging.config.dictConfig(dConfig) #读取配置文件
oLog = logging.getLogger("my_module") #获取指定logger
oLog.error("model test2")
if __name__ == "__main__":
LogFromJson()
进阶
1. 使用pysnoop调试工具
下载:pip install pysnooper
导入使用
from pysnooper import snoop
""" watch:关注属性,注意,watch是个元组;
depth:递归深度,默认为1
"testsnooplog.txt"把snoop追加输出到log文件中,可不填,默认输出到控制台
watch_explode:展开输出字典的值,个人感觉没啥用"""
@snoop("testsnooplog.txt", watch=("oTestA.m_Num",), depth=2)
def DoMain():
oTestA = CTestA()
oTestA.m_Num = 3 # 测试关注属性的变化
print(oTestA.m_Num)
# 测试字典变量追踪
dTempDict = {1: 1, 2: 2}
dTempDict[1] = 3 # 变量更改也会打印
if 1:
iTemp = GetSum(1, 2) # 测试递归深度
del oTestA.m_Num
"testsnooplog.txt“中的内容如下
Source path:... D:/study/python/pycode/python_study/调试.py
22:04:16.486441 call 24 def DoMain():
22:04:16.499442 line 25 oTestA = CTestA()
Starting var:.. self = <__main__.CTestA object at 0x01C04950>
22:04:16.506444 call 5 def __init__(self):
22:04:16.518447 line 6 self.m_Num = 1
22:04:16.524947 return 6 self.m_Num = 1
Return value:.. None
New var:....... oTestA = <__main__.CTestA object at 0x01C04950>
New var:....... oTestA.m_Num = 1
22:04:16.536450 line 26 oTestA.m_Num = 3 # 测试关注属性的变化
Modified var:.. oTestA.m_Num = 3
22:04:16.555453 line 27 print(oTestA.m_Num)
22:04:16.567956 line 29 dTempDict = {1: 1, 2: 2}
New var:....... dTempDict = {1: 1, 2: 2}
22:04:16.573956 line 30 dTempDict[1] = 3 # 变量更改也会打印
Modified var:.. dTempDict = {1: 3, 2: 2}
22:04:16.586458 line 32 iTemp = GetSum(1, 2) # 测试递归深度
Starting var:.. iNumA = 1
Starting var:.. iNumB = 2
22:04:16.598461 call 36 def GetSum(iNumA, iNumB):
22:04:16.616965 line 37 return iNumA + iNumB
22:04:16.622965 return 37 return iNumA + iNumB
Return value:.. 3
New var:....... iTemp = 3
22:04:16.633466 line 33 del oTestA.m_Num
22:04:16.645969 return 33 del oTestA.m_Num
Return value:.. None
Elapsed time: 00:00:00.171530
2. __setattr__方法
在更改某个实例的属性的时候,会调用__setattr__方法,
通过__setattr__我们可以追踪某个属性的更改,查看属性在什么时候被更改了
测试代码如下,类被初始化的时候调用一次__setattr__,更改的时候调用一次,总共两次
class CTestA(object):
def __init__(self):
self.m_Num = 1
def __setattr__(self, key, value):
if hasattr(self, key):
print("the attribute {} changed from {} to {}".format(key, self.__getattribute__(key), value))
else:
print("the attribute {} changed to {}".format(key, value))
super(CTestA, self).__setattr__(key, value)
if __name__ == "__main__":
oTestA = CTestA()
oTestA.m_Num = 3
print(oTestA.m_Num)
输出如下
D:\study\python3.6.8\python.exe D:/study/python/pycode/python_study/调试.py
the attribute m_Num changed to 1
the attribute m_Num changed from 1 to 3
3
Process finished with exit code 0
3. __delattr__方法
同2,在属性被删除的时候调用
在上面CTestA重写如下方法
def __delattr__(self, item):
print("the item {} has being delete".format(item))
super(CTestA, self).__delattr__(item)
然后再main中调用del oTestA.m_Num
输出如下
D:\study\python3.6.8\python.exe D:/study/python/pycode/python_study/调试.py
the attribute m_Num changed to 1
the attribute m_Num changed from 1 to 3
3
the item m_Num has being delete
Process finished with exit code 0