python - Twisted / perform asynchronous http requests -


i have twisted reactor listening incoming data. have second reactor performing http requests in time intervals sending results first reactor. both run fine.

now bring run in 1 reactor, not know how achieve this. - perform http requests every 60 sec. in asynchrounous way within first listening "main" reactor.

what have @ moment is:

# main reactor listening incoming data forever ... reactor.listentcp(8123, tcpeventreceiverfactory()) 

the http reactor uses twisted.internet.defer.deferredsemaphore() perform several http checks:

# create semaphore manage deferreds semaphore = twisted.internet.defer.deferredsemaphore(2)  # create list urls check dl = list() # append deferreds list url in self._urls:     # returns deferred     dl.append(semaphore.run(self._getpage, url))  # defferedlist dl = twisted.internet.defer.deferredlist(dl) # add callbacks error handling dl.addcallbacks(lambda x: reactor.stop(), self._handleerror)  # start reactor     reactor.run() 

how can add timed http checks "main" reactor, performed in asynchronous way? how deferredsemaphore work?

can me this?

[this kind of lightweight monitoring system processing http checkresults. new twisted , asynchronous programming. on xubuntu 12.04 running python 2.7]

you don't need multiple reactors. perform of different actions using same reactor.

if you're calling reactor.stop(), you're doing wrong, lets rid of that, , tie single function (that use callback); since doing asynchronous work, should return deferred, we'll use deferredlist you're using.

def thing_that_does_http():     # create semaphore manage deferreds     semaphore = twisted.internet.defer.deferredsemaphore(2)      # create list urls check     dl = deferredlist()     # append deferreds list     url in self._urls:         # returns deferred         dl.append(semaphore.run(self._getpage, url))      # defferedlist     dl = twisted.internet.defer.deferredlist(dl)     # add callbacks error handling     dl.adderrback(self._handleerror)     return dl 

the natural way "perform x in time intervals" looping call. callback function don't need much

reactor.listentcp(8123, tcpeventreceiverfactory()) loop_http = twisted.intertnet.task.loopingcall(thing_that_does_http) # run once per minute, starting now. loop_http.start(60) 

the reactor loopingcall , getpage use own purposes twisted.internet.reactor, if using different reactor, instance if doing unit testing, you'll need override default.

in case of loopingcall, it's quite simple, after construction, (but before calling start() method), set clock attribute:

from twisted.internet.task import clock fake_reactor = clock() loop_http.clock = fake_reactor fake_reactor.advance(120)  # move time forward 2 minutes... 

unfortunately, situation getpage() less nice. cannot use other reactor interface; you'll need use newer, shinier t.w.c.agent. in many ways agent superior, it's not quite convenient when want raw response body string.

aside requiring explicit reactor passed constructor, it's more fine grained control on request/response cycle convenience provided getpage. such it's implemented in terms of producers , protocols. in case of former, can pass convenience helper, filebodyproducer send request bodies minimal fuss; in latter, we'll need simple protocol buffer of chunks of data until we've gotten of it.

here's chunk of code replace getpage, same interface, taking instance of agent first argument

from cstringio import stringio twisted.internet.defer import deferred twisted.internet.protocol import protocol twisted.web.client import responsedone twisted.web.client import filebodyproducer   class getpageprotocol(protocol):     def __init__(self):         self.deferred = deferred()         self.data = []      def datareceived(self, data):         self.data.append(data)      def connectionlost(self, reason):         reason.trap(responsedone)         data = ''.join(self.data)         del self.data         self.deferred.callback(data)   def agentgetpage(agent, url,                  method="get",                  headers=none,                  postdata=none):     if postdata not none:         bodyproducer = filebodyproducer(stringio(postdata))     else:         bodyproducer = none      def _getpageresponded(response):         if response.length != 0:             proto = getpageprotocol()             response.deliverbody(proto)             return proto.deferred         else:             return none      d = agent.request(method, url, headers, bodyproducer)     d.addcallback(_getpageresponded)     return d 

which, in unit test, sort of like:

from twisted.test.proto_helpers import memoryreactor twisted.web.client import agent fake_reactor = memoryreactor() agent = agent(fake_reactor) d = agentgetpage(agent, "http://example.com")  assert fake_reactor.tcpclients  # or such, exercise code manipulating reactor 

edit: wanted skim on give ectomorph, less confused about; it's pretty idea drum in proper handling of reactors early, , avoid needless pain later.


Comments

Popular posts from this blog

php - mySql Join with 4 tables -

css - Text drops down with smaller window -

c# - DetailsView in ASP.Net - How to add another column on the side/add a control in each row? -