tnLog.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys import time import logging import inspect ''' import inspect def test(): a = inspect.stack()[1] print a 得到一个元组,如: (<frame object at 0x8604aa4>, 'test.py', 10, 'function_one', ['\t\tprint get_current_function_name()\n'], 0) a = inspect.stack()[1] 该行代码所在函数(被调函数)栈幀是0,根据调用的顺序,这个调用链条上的函数栈幀偏移值递增1
a -> b -> c (a调用b,b调用c)c中通过inspect获得栈幀集合,对于c来说
函数b的栈幀是inspect.stack()[1],函数a的栈幀是inspect.stack()[2]
那么这个元组的分别是:(调用者的栈对象,调用者的文件名,调用行数,调用者函数名,调用代码,0) 最后的0未知其含义 ''' class Logger(object): def printfNow(self): return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) def __init__(self): self.__logger = logging.getLogger() path = os.path.abspath("/tmp/TNLOG-error.log") handler=logging.FileHandler(path) self.__logger.addHandler(handler) self.__logger.setLevel(logging.NOTSET) def getLogMessage(self,level,message): #message = "[%s] %s " %(self.printfNow(),message) frame,filename,lineNo,functionName,code,unknowField = inspect.stack()[2] '''日志格式:[时间] [类型] [记录代码] 信息''' return "[%s] [%s] [%s - %s - %s] %s" %(self.printfNow(),level,filename,lineNo,functionName,message) def info(self,message): message = self.getLogMessage("info",message) self.__logger.info(message) def error(self,message): message = self.getLogMessage("error",message) self.__logger.error(message) def warning(self,message): message = self.getLogMessage("warning",message) self.__logger.warning(message) def debug(self,message): message = self.getLogMessage("debug",message) self.__logger.debug(message) def critical(self,message): message = self.getLogMessage("critical",message) self.__logger.critical(message) #logger = consoleLog() if __name__ == "__main__": logger = Logger() logger.info("hello")
main.py
import sys import tnLog class X: def test(self): logger = tnLog.Logger() logger.info("hello") if __name__ == "__main__": x = X() x.test()
另外在python里可以读栈幀结构的库是traceback模块,不过使用这个模块需要先触发异常
镇宅神兽2012-08-14 14:48:47
被调函数怎么才能知道,是谁调用的我(调用我的函数,它的模块名,文件名,函数名,导致调用语句的行数)
镇宅神兽2012-08-14 14:48:55
在python里
salary-北京2012-08-14 16:28:57
>>> import inspect
>>> def f1(): f2()
...
>>> def f2():
... print '%s, %s' %(inspect.stack()[0][3],inspect.stack()[1][3])
...
>>> f1()
f2, f1
文武 pm 北京2012-08-14 16:30:36
正解
文武 pm 北京2012-08-14 16:30:42
看来大家都在玩儿python啊
GZ_change#小白2012-08-14 16:31:25
python这么好玩儿?
文武 pm 北京2012-08-14 16:31:39
那当然
文武 pm 北京2012-08-14 16:31:45
python干活真的很有效率
GZ_change#小白2012-08-14 16:31:53
昨天看 黑客 与画家
GZ_change#小白2012-08-14 16:32:14
动态语言,确实用着挺爽
镇宅神兽2012-08-14 17:38:33
我搞定了
GZ_change#小白2012-08-14 17:39:08
神马?
镇宅神兽2012-08-14 17:39:24
http://www.cnblogs.com/kill-signal/archive/2012/08/14/2638255.html
镇宅神兽2012-08-14 17:39:36
写的不错吧
镇宅神兽2012-08-14 17:39:56
我现在觉得,没有一定的LOG简直找死
镇宅神兽2012-08-14 17:40:07
调试个啥太困难了
GZ_change#小白2012-08-14 17:40:46
能用一句中文说明一下你的这篇博客写的是啥?
镇宅神兽2012-08-14 17:40:50
API,甚至全部函数都可以在入口把参数值记下来
镇宅神兽2012-08-14 17:41:32
这种东西,在后期排错帮助太大了
镇宅神兽2012-08-14 17:42:35
这么简单的东西要解释嘛
salary-北京2012-08-14 17:42:56
嗯,不错,值得学习。
GZ_change#小白2012-08-14 17:43:05
这个事情我也干过
GZ_change#小白2012-08-14 17:43:24
之前写一个单片机上面的数据存储管理模块
GZ_change#小白2012-08-14 17:43:35
不过都是手工写的打印函数
GZ_change#小白2012-08-14 17:43:37
printf
镇宅神兽2012-08-14 17:43:42
没有这些LOG,程序TMD就是一个黑盒
GZ_change#小白2012-08-14 17:44:09
你知道
GZ_change#小白2012-08-14 17:44:17
那些单片机是没有屏幕的
GZ_change#小白2012-08-14 17:44:29
调试程序,就是,把程序烧进去
GZ_change#小白2012-08-14 17:44:37
接上串口线
镇宅神兽2012-08-14 17:44:37
哪你能不能写文本文件呢
GZ_change#小白2012-08-14 17:44:43
不能
镇宅神兽2012-08-14 17:44:49
要对LOG封一层
GZ_change#小白2012-08-14 17:44:54
因为容量只有多少K而已
GZ_change#小白2012-08-14 17:45:03
而且,文件拷贝不出来
镇宅神兽2012-08-14 17:45:04
方便扩展行为
GZ_change#小白2012-08-14 17:45:08
只能烧程序进去
GZ_change#小白2012-08-14 17:45:15
所以,就只能靠printf
GZ_change#小白2012-08-14 17:45:28
打印到串口
镇宅神兽2012-08-14 17:45:28
如果这样的话,printf倒也可以接受
GZ_change#小白2012-08-14 17:45:35
在PC机器上看printf
GZ_change#小白2012-08-14 17:45:47
的数据
GZ_change#小白2012-08-14 17:45:59
太TM蛋疼了
GZ_change#小白2012-08-14 17:46:02
我去
镇宅神兽2012-08-14 17:46:39
武总,你们谁推荐个日志分析工具
镇宅神兽2012-08-14 17:47:47
整个系统应该遍布LOG
镇宅神兽2012-08-14 17:48:11
这样程序的状态才是可知,易排错的
镇宅神兽2012-08-14 17:48:24
最后,我们需要一个开关
镇宅神兽2012-08-14 17:48:53
系统稳定后可以少打一些LOG