Faire un programme python attendre jusqu'à ce que Twisted retours différé une valeur
Question
J'ai un programme qui va chercher les informations d'autres pages et Parsis en les utilisant BeautifulSoup et getPage de Twisted. Plus tard dans le programme d'information imprimer que le processus différé crée. Actuellement, mon programme tente d'imprimer avant le retour d'information de la différé. Comment puis-je attendre?
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
La solution
Ce qu'il semble que vous essayez de faire / exécuter plusieurs réacteurs. Tout est attaché à la même réacteur. Voici comment utiliser un DeferredList
attendre tous vos callbacks à la fin.
Notez également que twisAmaz
retourne une valeur. Cette valeur est passée à travers le callbacks
de DeferredList
et sort comme value
. Puisqu'un DeferredList
conserve l'ordre des choses qui sont mises en, vous pouvez recouper l'indice des résultats avec l'index de vos numéros 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()
Autres conseils
Une autre façon cool de le faire est avec @ defer.inlineCallbacks. Il vous permet d'écrire du code asynchrone comme une fonction séquentielle régulière: http : //twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html#inlineCallbacks
Tout d'abord, vous ne devriez pas mettre un reactor.stop () dans votre méthode différée, car il tue tout.
Maintenant, dans Twisted, "Waiting" est pas autorisé. Pour imprimer les résultats de vous rappel, il suffit d'ajouter un autre rappel après la première.