2010-08-15 12 views
8

Tengo un programa que obtiene información de otras páginas y las analiza usando BeautifulSoup y Twisted's getPage. Más adelante en el programa, imprimo información que crea el proceso diferido. Actualmente mi programa intenta imprimirlo antes de que el diferido devuelva la información. ¿Cómo puedo hacer que espere?Haciendo que un programa python espere hasta que Twisted deferred devuelva un valor

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 
+0

¿de verdad está usando 1 espacio para la sangría ... –

+0

Eso era un problema de formateo aquí, el código real usa la pestaña –

Respuesta

8

Lo que parece que está tratando de hacer/ejecutar múltiples reactores. Todo se adjunta al mismo reactor. A continuación, le indicamos cómo usar un DeferredList para esperar a que finalicen todas sus devoluciones de llamada.

También tenga en cuenta que twisAmaz devuelve un valor. Ese valor se pasa a través del callbacksDeferredList y sale como value. Dado que DeferredList mantiene el orden de las cosas que se ponen en él, puede hacer una referencia cruzada del índice de los resultados con el índice de sus 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() 
+0

Se ve bien, gracias Aaron! –

2

En primer lugar, no debe poner un reactor.stop() en su método diferido, ya que mata todo.

Ahora, en Twisted, "Esperar" no está permitido. Para imprimir los resultados de su devolución de llamada, simplemente agregue otra devolución de llamada después de la primera.

+0

Gracias, Luc! ¿Puedo preguntar dónde debería ir el reactor.stop()? –

+0

Cuando dije que no pusiera un reactor.stop(), quise no ponerlo en ese primer código diferido, ya que lo detendría todo. Así que debería ponerlo en el último diferido (el que imprime los resultados) donde está seguro de que desea detener su programa. Solo una nota: debe usar addCallbacks (method1, error_method) para detectar posibles errores. –

+0

Mire el tutorial sobre diferido en http://twistedmatrix.com/documents/current/core/howto/deferredindepth.html, especialmente la sección llamada 'Callbacks puede devolver diferidos'. –

Cuestiones relacionadas