Thursday, August 19, 2010

Learning Twisted (part 1) : reactor basics

Twisted framework is an event based networking framework in Python. This description suffices for initial impression about this framework.

These and subsequent posts will serve as my notes for learning Twisted.

At the core of event based programming is reactor loop that run endlessly unless asked to stop.
While in the loop, reactor listens to events and dispatches these events to event handlers for processing of events. The example below is the simplest way of starting up the reactor.

print("To stop this example, press ctrl-c")
from twisted.internet import reactor
reactor.run()

reactor.run() should be the last line of code that gets executed immediately. After this, the control is handed to reactor loop, which listens for events endlessly. Some of the methods of this class also allows you to register for events and event handlers to process something real.

There are many reactors available, which needs to be installed. Default reactor is select based reactor - "SelectReactor"


Twisted framework uses it's own logging mechanism. At the moment, we will see a simple use of logging, till I understand logging better.

import sys
from twisted.internet import reactor
from twisted.python import log
# Log to standard output
log.startLogging(sys.stdout)
print "\nTo stop this example, press ctrl-c\n"
reactor.run()

There are default system signal handlers. When ever a signal is recieved, reactor dispatches them to these handlers. Some of them are : sigInt, sigTerm, sigBreak. In the above example, you can see the log message from sigInt. The above code is a dull piece of code, since there are no interesting events and event handlers registered with the reactor.

The capabilities in Twisted are defined at twisted.internet.interface.py. twisted.internet.base.py implements the base capabilities as defined in class IReactorCore.  This provides a mechanism to register an handler for an event which is fired when reactor starts running in listen loop - callWhenRunning.

import sys
from twisted.internet import reactor
from twisted.python import log
log.startLogging(sys.stdout)

def callfunc(x):
    log.msg("In callfunc as event handler")
    log.msg(str(x))
    log.msg("Will shut down")
    reactor.stop()
   
reactor.callWhenRunning(callfunc, "This was passed to callfunc")
reactor.run()
Core reactor functionalities as implemented in twisted.internet.base.py
+----------------+
|  IReactorCore  |    +--------------+    XXXXXXXXXXXXXXXXXX
|                |..... IReactorTime |... X                X
|                |    +--------------+    X  IDelayedCall  X
+----------------+                        X                X
                                          XXXXXXXXXXXXXXXXXX
IReactorTime provides a way to register a function to be called after some delay.

import sys, time
from twisted.internet import reactor
from twisted.python import log
log.startLogging(sys.stdout)

def callfunc(x):
    log.msg(str(x))
    now = time.localtime(time.time())
    log.msg(str(time.strftime("%y/%m/%d %H:%M:%S",now)))
    log.msg("Will stop")
    reactor.stop() # try calling reactor.sigInt() or crash() etc
   
now = time.localtime(time.time())
log.msg("str(time.strftime("%y/%m/%d %H:%M:%S",now)))
_DelayedCallObj = reactor.callLater(4, callfunc, "callfunc called after 4 sec")
reactor.run()

callLater function returns a DelayedCall object. You can cancel , delay or reset it's timer.

So far, we have seen some event handlers and events available when reactor gets started. You could add your own custome events and eventHandlers, use the recator to fire the events and let it dispatch it to your custome event handler.

import sys, time
from twisted.internet import reactor
from twisted.python import log
log.startLogging(sys.stdout)

def callfunc(x):
    log.msg(str(x))
    now = time.localtime(time.time())
    log.msg("str(time.strftime("%y/%m/%d %H:%M:%S",now)))
    log.msg("Fire Event1 after 4 seconds")
    reactor.callLater(4, reactor.fireSystemEvent, 'Event1')
       
def Event1_CustomEventHandler():
    now = time.localtime(time.time())
    log.msg("str(time.strftime("%y/%m/%d %H:%M:%S",now)))
    log.msg("In Event1_CustomEventHandler .., shutting down")
    reactor.stop()
       
now = time.localtime(time.time())
log.msg(str(time.strftime("%y/%m/%d %H:%M:%S",now)))
_DelayedCallObj = reactor.callLater(4, callfunc, "callfunc called after 4 sec")
reactor.addSystemEventTrigger('during', 'Event1', Event1_CustomEventHandler)
reactor.run()

Like the above example, you could register system signal event handlers too. This way, you can trap certain signal and do your own custom shutdown.

import sys
from twisted.internet import reactor
from twisted.python import log
log.startLogging(sys.stdout)
import signal

def SIGINT_CustomEventHandler(num, frame):
    k={1:"SIGHUP", 2:"SIGINT"}
    log.msg("Recieved signal - " + k[num])
    if frame is not None:
        log.msg("SIGINT at %s:%s"%(frame.f_code.co_name, frame.f_lineno))
    log.msg("In SIGINT_CustomEventHandler")
    if num == 2:
        log.msg("shutting down ....")
        reactor.stop()

signal.signal(signal.SIGINT, SIGINT_CustomEventHandler)
signal.signal(signal.SIGHUP, SIGINT_CustomEventHandler)
reactor.run()


This should suffice to show some of the basic aspects of a reactor, events and event handlers.

8 comments:

  1. Hello!
    In example of a function is called after some delay:
    log.msg("str(time.strftime("%y/%m/%d %H:%M:%S",now)))

    first mark " excess.

    ReplyDelete
  2. Great post, thanks!

    ReplyDelete
  3. Whether you are a new trader or an experienced trader, Online Stock Broker provides all of the information you need to make an educated decision about which online broker to use. We have years of experience in this industry working alongside brokers, traders and market makers and we bring our knowledge and expertise to you with this guide.

    ReplyDelete
  4. https://learningenglishwithmichelle.blogspot.com/2013/06/why-i-love-canada.html?showComment=1642571948046#c4581260638357740874

    ReplyDelete
  5. Fxit Stock Overview: Stay ahead of the market with our live and real time stock market overview. Get all of your favorite stocks in one place, and get alerted to live news at the same time!

    ReplyDelete
  6. Gteh Stocktwits Real-Time Overview Of A Stock, Including Recent And Historical Price Charts, News, Events, Analyst Rating Changes And Other Key Stock Information.

    ReplyDelete