1""" 2Some utility classes for exception handling of exceptions raised 3within listeners: 4 5- TracebackInfo: convenient way of getting stack trace of latest 6 exception raised. The handler can create the instance to retrieve 7 the stack trace and then log it, present it to user, etc. 8- ExcPublisher: example handler that publishes a message containing 9 traceback info 10 11:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved. 12:license: BSD, see LICENSE_BSD_Simple.txt for details. 13 14""" 15 16 17import sys, traceback 18 19from ..core.listener import IListenerExcHandler 20 21 22class TracebackInfo: 23 """ 24 Represent the traceback information for when an exception is 25 raised -- but not caught -- in a listener. The complete 26 traceback cannot be stored since this leads to circular 27 references (see docs for sys.exc_info()) which keeps 28 listeners alive even after the application is no longer 29 referring to them. 30 31 Instances of this object are given to listeners of the 32 'uncaughtExcInListener' topic as the excTraceback kwarg. 33 The instance calls sys.exc_info() to get the traceback 34 info but keeps only the following info: 35 36 * self.ExcClass: the class of exception that was raised and not caught 37 * self.excArg: the argument given to exception when raised 38 * self.traceback: list of quadruples as returned by traceback.extract_tb() 39 40 Normally you just need to call one of the two getFormatted() methods. 41 """ 42 def __init__(self): 43 tmpInfo = sys.exc_info() 44 self.ExcClass = tmpInfo[0] 45 self.excArg = tmpInfo[1] 46 # for the traceback, skip the first 3 entries, since they relate to 47 # implementation details for pubsub. 48 self.traceback = traceback.extract_tb(tmpInfo[2])[3:] 49 # help avoid circular refs 50 del tmpInfo 51 52 def getFormattedList(self): 53 """Get a list of strings as returned by the traceback module's 54 format_list() and format_exception_only() functions.""" 55 tmp = traceback.format_list(self.traceback) 56 tmp.extend( traceback.format_exception_only(self.ExcClass, self.excArg) ) 57 return tmp 58 59 def getFormattedString(self): 60 """Get a string similar to the stack trace that gets printed 61 to stdout by Python interpreter when an exception is not caught.""" 62 return ''.join(self.getFormattedList()) 63 64 def __str__(self): 65 return self.getFormattedString() 66 67 68class ExcPublisher(IListenerExcHandler): 69 """ 70 Example exception handler that simply publishes the exception traceback 71 as a message of topic name given by topicUncaughtExc. 72 """ 73 74 # name of the topic 75 topicUncaughtExc = 'uncaughtExcInListener' 76 77 def __init__(self, topicMgr=None): 78 """If topic manager is specified, will automatically call init(). 79 Otherwise, caller must call init() after pubsub imported. See 80 pub.setListenerExcHandler().""" 81 if topicMgr is not None: 82 self.init(topicMgr) 83 84 def init(self, topicMgr): 85 """Must be called only after pubsub has been imported since this 86 handler creates a pubsub topic.""" 87 obj = topicMgr.getOrCreateTopic(self.topicUncaughtExc) 88 obj.setDescription('generated when a listener raises an exception') 89 obj.setMsgArgSpec( dict( 90 listenerStr = 'string representation of listener', 91 excTraceback = 'instance of TracebackInfo containing exception info')) 92 self.__topicObj = obj 93 94 def __call__(self, listenerID, topicObj): 95 """Handle the exception raised by given listener. Send the 96 Traceback to all subscribers of topic self.topicUncaughtExc. """ 97 tbInfo = TracebackInfo() 98 self.__topicObj.publish(listenerStr=listenerID, excTraceback=tbInfo) 99 100 101