9 Stimmen

Ein Python-Programm warten lassen, bis Twisted deferred einen Wert zurückgibt

Ich habe ein Programm, das Informationen von anderen Seiten abruft und sie mit BeautifulSoup und Twisted's getPage analysiert. Später im Programm drucke ich die Informationen aus, die der verzögerte Prozess erzeugt. Momentan versucht mein Programm, die Informationen zu drucken, bevor der Prozess die Informationen zurückgibt. Wie kann ich es dazu bringen, zu warten?

def twisAmaz(contents): #This parses the page (amazon api xml file)
    stonesoup = BeautifulStoneSoup(contents)
    if stonesoup.find("mediumimage") == None:
       imageurl.append("/images/notfound.png")
    else:
      imageurl.append(stonesoup.find("mediumimage").url.contents[0])

    usedPdata = stonesoup.find("lowestusedprice")
    newPdata = stonesoup.find("lowestnewprice")
    titledata = stonesoup.find("title")
    reviewdata = stonesoup.find("editorialreview")

    if stonesoup.find("asin") != None:
        asin.append(stonesoup.find("asin").contents[0])
    else:
        asin.append("None")
    reactor.stop()

deferred = dict()
for tmpISBN in isbn:  #Go through ISBN numbers and get Amazon API information for each
    deferred[(tmpISBN)] = getPage(fetchInfo(tmpISBN))
    deferred[(tmpISBN)].addCallback(twisAmaz)
    reactor.run()

.....print info on each ISBN

9voto

habnabit Punkte 9240

Es sieht so aus, als ob Sie versuchen, mehrere Reaktoren zu bauen/zu betreiben. Alles wird mit dem dieselbe Reaktor. Hier erfahren Sie, wie Sie einen DeferredList um zu warten, bis alle Ihre Rückrufe beendet sind.

Beachten Sie auch, dass twisAmaz gibt einen Wert zurück. Dieser Wert wird durch die callbacks DeferredList und ergibt sich als value . Da eine DeferredList die Reihenfolge der eingegebenen Daten beibehält, können Sie den Index der Ergebnisse mit dem Index Ihrer ISBNs abgleichen.

from twisted.internet import defer

def twisAmazon(contents):
    stonesoup = BeautifulStoneSoup(contents)
    ret = {}
    if stonesoup.find("mediumimage") is None:
        ret['imageurl'] = "/images/notfound.png"
    else:
        ret['imageurl'] = stonesoup.find("mediumimage").url.contents[0]
    ret['usedPdata'] = stonesoup.find("lowestusedprice")
    ret['newPdata'] = stonesoup.find("lowestnewprice")
    ret['titledata'] = stonesoup.find("title")
    ret['reviewdata'] = stonesoup.find("editorialreview")
    if stonesoup.find("asin") is not None:
        ret['asin'] = stonesoup.find("asin").contents[0]
    else:
        ret['asin'] = 'None'
    return ret

callbacks = []
for tmpISBN in isbn:  #Go through ISBN numbers and get Amazon API information for each
    callbacks.append(getPage(fetchInfo(tmpISBN)).addCallback(twisAmazon))

def printResult(result):
    for e, (success, value) in enumerate(result):
        print ('[%r]:' % isbn[e]),
        if success:
            print 'Success:', value
        else:
            print 'Failure:', value.getErrorMessage()

callbacks = defer.DeferredList(callbacks)
callbacks.addCallback(printResult)

reactor.run()

4voto

Thomas Dignan Punkte 6956

Eine weitere gute Möglichkeit ist @defer.inlineCallbacks. Damit können Sie asynchronen Code wie eine normale sequenzielle Funktion schreiben: http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html#inlineCallbacks

2voto

Luc Stepniewski Punkte 316

Erstens sollten Sie kein reactor.stop() in Ihre Deferred-Methode einfügen, da es alles abbricht.

In Twisted ist das "Warten" nicht erlaubt. Um die Ergebnisse Ihres Rückrufs zu drucken, fügen Sie einfach einen weiteren Rückruf nach dem ersten ein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X