在Windows下debug程式時,有時候會遇到debug的輸出實在太多,難以尋找有用的資訊時,可以用OutputDebugString這個function將輸出導到debugger去。
但是在python下要怎麼做這件事呢?
我們可以ctypes這個模組來load OutputDebugString這個function,如下所示:
import ctypes
funcA = ctypes.windll.kernel32.OutputDebugStringA
funcW = ctypes.windll.kernel32.OutputDebugStringW
funcA('testing')
funcW(u'testing')
其中因為OutputDebugString有unicode和non-unicode兩個版本,分別是OutputDebugStringW和OutputDebugStringA。因此對python的string和unicode string分別呼叫不同的function。
最後,將這個功能加到上一篇的Logger裡,就是下面的code了:
import inspect
import os
class Logger( object):
LEVEL_MESSAGE, LEVEL_WARNING, LEVEL_ERROR, LEVEL_CRITICAL = range( 4)
LEVEL_MIN_VALUE = LEVEL_MESSAGE
LEVEL_MAX_VALUE = LEVEL_CRITICAL
@staticmethod
def __getLevelName( level):
if level == Logger.LEVEL_MESSAGE:
return 'MESSAGE'
elif level == Logger.LEVEL_WARNING:
return 'WARNING'
elif level == Logger.LEVEL_ERROR:
return 'ERROR'
elif level == Logger.LEVEL_CRITICAL:
return 'CRITICAL'
else:
return 'UNKNOWN'
__slots__ = ( '__logLevel', '__debugStream')
def __init__( self, logLevel = LEVEL_WARNING, enableWinDebug = False):
self.__initVariables( logLevel)
if os.name == 'nt' and enableWinDebug:
self.__initWinDebug()
def __initVariables( self, logLevel):
self.__logLevel = logLevel
self.__debugStream = None
def __initWinDebug( self):
import ctypes
self.__debugStream = { str: ctypes.windll.kernel32.OutputDebugStringA, unicode: ctypes.windll.kernel32.OutputDebugStringW}
@property
def logLevel( self):
return self.__logLevel
@logLevel.setter
def logLevel( self, logLevel):
if logLevel < Logger.LEVEL_MIN_VALUE or Logger.LEVEL_MAX_VALUE < logLevel:
raise ValueError, 'Invalid Log Level(%d)' % logLevel
self.__logLevel = logLevel
def log( self, logLevel, message, reverseStackCount = 1):
if logLevel >= self.logLevel:
stack = inspect.stack()
if len( stack) >= reverseStackCount:
frame = stack[ reverseStackCount]
file = os.path.split( frame[ 1])[ 1]
output = '[%s] [%s:%d] [%s] %s' % ( Logger.__getLevelName( logLevel), file, frame[ 2], frame[ 3], message)
if self.__debugStream:
self.__debugStream[ type( output)]( output)
print output
def message( self, message):
self.log( Logger.LEVEL_MESSAGE, message, reverseStackCount = 2)
def warning( self, message):
self.log( Logger.LEVEL_WARNING, message, reverseStackCount = 2)
def error( self, message):
self.log( Logger.LEVEL_ERROR, message, reverseStackCount = 2)
def critical( self, message):
self.log( Logger.LEVEL_CRITICAL, message, reverseStackCount = 2)
留言列表