Table Of Contents

Previous topic

Advanced Usage

Next topic

Types of Errors

This Page

Debugging an application

Types of Errors

While developing an application that uses pubsub, calls to pubsub functions and methods may raise an exception. These are discussed in:

Notification: Tracking pubsub activity

Pubsub can call a specified handler every time it performs a certain task:

  • subscribe: whenever a listener subscribes to a topic
  • unsubscribe: whenever a listener unsubscribes from a topic
  • deadListener: whenever pubsub finds out that a listener has died
  • send: whenever the user calls sendMessage()
  • newTopic: whenever the user defines a new topic
  • delTopic: whenever the user undefines a topic

A notification handler must adhere to the pub.INotificationHandler:

import pubsub.utils
class MyNotifHandler(INotificationHandler):
        def onSendMessage(...):
    ...

pub.addNotificationHandler( MyNotifHandler() )

A simple handler class is available already in pubsub.utils: notification.NotifyByPubsubMessage. This handler takes each notification received and generates a pubsub message of a “pubsub.” topic named after the operation, such as “pubsub.subscribe”. To use notification via this notifier, you must register one or more listeners for the “pubsub.*” topics of interest.

A utility function is available from pubsub.utils for the most common case:

from pubsub.utils import notification
notification.useNotifyByPubsubMessage()

Naughty Listeners: Trap Exceptions

A sender has no way of knowing what can go wrong during message handling by the subscribed listeners. As a result, a listener must not raise any exceptions (or rather, must not let any exceptions escape): if an exception does escape a listener, it interrupts the pub.sendMessage() call such that some listeners may not be sent the message. Putting a try/except clause around every sendMessage is typically not practical.

Since exceptions are common during application development (bugs due to invalid arguments, failed assertions, etc), pubsub provdes a hook to register a ‘listener exception’ handler: whenever a listener raises an exception, pubsub then sends it to the handler, and continues with the send operation until all listeners have received the message. The handler might print it to a log file, output a message in a status bar, show an error box, etc. The handling itself is very application-specific, hence this strategy.

The handler must adhere to the pub.IListenerExcHandler protocol. An instance of the handler can be given to pub.setListenerExcHandler().

Listen for messages from all topics

Pubsub defines a specia topic named pub.ALL_TOPICS. A listener that subscribes to this topic will receives all messages of every topic. By default, the listener will not receive any data since pub.ALL_TOPICS is the parent of all root topics: its MDS must be empty.

However, any listener that is a callable with a “catch-all” **kwargs parameter will be given all message data. Moreover, pubsub sends the topic object automatically with the message data if it finds that listener accepts a keyword argument with a default value of pub.AUTO_TOPIC. Together, these can be used to obtain complete information about all messages:

>>> def snoop(topicObj=pub.AUTO_TOPIC, **mesgData):
>>>     print 'topic "%s": %s' % (topicObj.getName(), mesgData)
>>>
>>> pub.subscribe(snoop, pub.ALL_TOPICS)
(<pubsub.core.listenerimpl.Listener instance at 0x01A040A8>, True)
>>> pub.sendMessage('some.topic.name', a=1, b=2)
topic "some.topic.name": {'a': 1, 'b': 2}

Using the pub.Listener class

Every callable that is subscribed via pub.subscribe() is wrapped in a pub.Listener instance returned by this function. This class has several useful functions such as name(), typeName(), module(), and isDead(). For example:

>>> def snoop(topicObj=pub.AUTO_TOPIC, **mesgData):
>>>     pass
>>>
>>> pubListener, first = pub.subscribe(snoop, pub.ALL_TOPICS)
>>> assert first == true # since first time subscribed
>>> assert pubListener.isDead() == false
>>> assert pubListener.wantsTopicObjOnCall() == true
>>> assert pubListener.wantsAllMessageData() == true
>>> print pubListener.name()
snoop_2752
>>> print pubListener.name()
snoop

Doing something with every topic

Derive from pub.ITopicTreeVisitor and give instance to an instance of pub.TopicTreeTraverser, then call traverse() method. For example, assume a callable ‘listener’ has been subscribed to several topics. An easy way to verify all topics subscribed to use this:

>>> class MyVisitor(pub.ITopicTreeVisitor):
>>>    def __init__(self, listener):
>>>        self.subscribed = []
>>>        self.listener = listener
>>>    def _onTopic(self, topicObj):
>>>        if (topicObj.hasListener(self.listener))
>>>            self.subscribed.append(topicObj.getName())
>>>
>>> tester = new MyVisitor(listener)
>>> traverser = pub.TopicTreeTraverser( tester )
>>> traverser.traverse(pub.getDefaultTopicTreeRoot())
>>> print tester.subscribed
['topic-name', 'topic-name2', ...]

Printing Topic Tree

See pubsub.utils.printTreeDocs().