Hacer una espera hasta que el programa pitón Twisted diferido devuelve un valor
Pregunta
Tengo un programa que recupera la información de otras páginas y analiza ellos utilizando BeautifulSoup y getPage de trenzado. Más tarde en el programa puedo imprimir información de que el proceso crea diferido. Actualmente mi programa intenta imprimirlo antes de que vuelva diferían de la información. ¿Cómo puedo hacer que esperar?
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
Solución
Lo que parece es que estamos tratando de hacer correr / múltiples reactores. Todo se une a la mismo reactor. Aquí es cómo utilizar un DeferredList
que esperar a que todos sus devoluciones de llamada a fin.
Tenga en cuenta también que twisAmaz
devuelve un valor. Ese valor se pasa a través de la callbacks
DeferredList
y sale como value
. Desde un DeferredList
mantiene el orden de las cosas que se ponen en ella, puede hacer una referencia cruzada el índice de los resultados con el índice de sus números ISBN.
from twisted.internet import defer
def twisAmaz(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()
Otros consejos
Otra manera fresca de hacerlo es con @ defer.inlineCallbacks. Se le permite escribir código asíncrono como una función secuencial normal: http : //twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html#inlineCallbacks
En primer lugar, no debe poner un reactor.stop () en el método diferido, ya que mata todo.
Ahora, en Twisted, no está permitido "en espera". Para imprimir los resultados de devolución de llamada, sólo tiene que añadir otra llamada de retorno después de la primera.