Twisted:hoekom is dit dat die verbygaan van'n uitgestelde terugbel om'n uitgestelde draad maak die draad sluit al van'n skielike?

StackOverflow https://stackoverflow.com/questions/2466000

Vra

Ek onsuksesvol probeer om met behulp van txredis (die nie sluit gedraai api vir redis) vir'n volhard boodskap ry ek probeer om op te rig met'n scrapy projek wat ek werk op.Ek het gevind dat hoewel die kliënt was nie sluit, was dit baie stadiger as wat dit kon gewees het, want wat moet gewees het een gebeurtenis in die reaktor lus was verdeel in duisende van die stappe.

So in plaas daarvan, het ek probeer om gebruik te maak van redis-py (die gereelde sluit gedraai api) en wikkel die oproep in'n uitgestelde draad.Dit werk baie goed, maar ek wil om uit te voer'n innerlike uitgestel wanneer ek maak'n oproep te redis as ek wil om te stel verband pooling in pogings om dinge te bespoedig verder.

Hieronder is my interpretasie van'n paar monster kode geneem uit die gedraaide dokumente vir'n uitgestelde draad te illustreer my gebruik geval:

#!/usr/bin/env python
from twisted.internet import reactor,threads
from twisted.internet.task import LoopingCall
import time

def main_loop():
    print 'doing stuff in main loop.. do not block me!'


def aBlockingRedisCall():
    print 'doing lookup... this may take a while'
    time.sleep(10)
    return 'results from redis'

def result(res):
    print res

def main():
    lc = LoopingCall(main_loop)
    lc.start(2)
    d = threads.deferToThread(aBlockingRedisCall)
    d.addCallback(result)
    reactor.run()

if __name__=='__main__':
    main()

En hier is my verandering vir die aansluiting pooling wat maak dat die kode in die uitgestelde draad sluit :

#!/usr/bin/env python
from twisted.internet import reactor,defer
from twisted.internet.task import LoopingCall
import time

def main_loop():
    print 'doing stuff in main loop.. do not block me!'

def aBlockingRedisCall(x):
    if x<5: #all connections are busy, try later
        print '%s is less than 5, get a redis client later' % x
        x+=1
        d = defer.Deferred()
        d.addCallback(aBlockingRedisCall)
        reactor.callLater(1.0,d.callback,x)
        return d

    else: 
        print 'got a redis client; doing lookup.. this may take a while'
        time.sleep(10) # this is now blocking.. any ideas?
        d = defer.Deferred()
        d.addCallback(gotFinalResult)
        d.callback(x)
        return d

def gotFinalResult(x):
    return 'final result is %s' % x

def result(res):
    print res

def aBlockingMethod():
    print 'going to sleep...'
    time.sleep(10)
    print 'woke up'

def main():
    lc = LoopingCall(main_loop)
    lc.start(2)


    d = defer.Deferred()
    d.addCallback(aBlockingRedisCall)
    d.addCallback(result)
    reactor.callInThread(d.callback, 1)
    reactor.run()

if __name__=='__main__':
    main()

So my vraag is, is daar iemand wat weet hoekom my verandering veroorsaak dat die uitgestelde draad te sluit en/of kan iemand stel voor dat'n beter oplossing?

Was dit nuttig?

Oplossing

Wel, as die gedraai docs sê:

  

Deferreds nie die kode maak   Nou nie blok

Wanneer jy gebruik blokkeer kode, soos sleep, moet jy dit stel om 'n nuwe draad.

#!/usr/bin/env python
from twisted.internet import reactor,defer, threads
from twisted.internet.task import LoopingCall
import time

def main_loop():
    print 'doing stuff in main loop.. do not block me!'

def aBlockingRedisCall(x):
    if x<5: #all connections are busy, try later
        print '%s is less than 5, get a redis client later' % x
        x+=1
        d = defer.Deferred()
        d.addCallback(aBlockingRedisCall)
        reactor.callLater(1.0,d.callback,x)
        return d

    else: 
        print 'got a redis client; doing lookup.. this may take a while'
        def getstuff( x ):
            time.sleep(3)
            return "stuff is %s" % x

        # getstuff is blocking, so you need to push it to a new thread
        d = threads.deferToThread(getstuff, x)
        d.addCallback(gotFinalResult)
        return d

def gotFinalResult(x):
    return 'final result is %s' % x

def result(res):
    print res

def aBlockingMethod():
    print 'going to sleep...'
    time.sleep(10)
    print 'woke up'

def main():
    lc = LoopingCall(main_loop)
    lc.start(2)


    d = defer.Deferred()
    d.addCallback(aBlockingRedisCall)
    d.addCallback(result)
    reactor.callInThread(d.callback, 1)
    reactor.run()

if __name__=='__main__':
    main()

In die geval van die redis api is nie baie kompleks is dit dalk meer natuurlike om dit te herskryf met behulp van twisted.web wees, in plaas van net die roeping van die sluit van api in 'n baie drade.

Ander wenke

Daar is ook 'n up-to-date Redis kliënt vir gedraai wat reeds ondersteun die nuwe protokol en funksies van Redis 2.x Jy moet definetely gee dit 'n probeer. Dit is bekend as txredisapi.

Vir die aanhoudende boodskap tou, ek wil RestMQ beveel. A-redis gebaseer boodskap tou stelsel gebou op die top van sikloon en txredisapi.

http://github.com/gleicon/restmq

Cheers

Op 'n verwante noot, jy kan waarskynlik 'n baie te doen met behulp van 'n Redis kliënt spesifiek geskep vir Twisted, soos hierdie een: http://github.com/deldotdr/txRedis

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top