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 XXXXXXXXXXXXXXXXXXIReactorTime 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.
Hello!
ReplyDeleteIn example of a function is called after some delay:
log.msg("str(time.strftime("%y/%m/%d %H:%M:%S",now)))
first mark " excess.
Great post, thanks!
ReplyDeleteThanks. Well explained!
ReplyDeletethanks for this....
ReplyDeleteWhether 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.
ReplyDeletehttps://learningenglishwithmichelle.blogspot.com/2013/06/why-i-love-canada.html?showComment=1642571948046#c4581260638357740874
ReplyDeleteFxit 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!
ReplyDeleteGteh Stocktwits Real-Time Overview Of A Stock, Including Recent And Historical Price Charts, News, Events, Analyst Rating Changes And Other Key Stock Information.
ReplyDelete