Заставить программу на Python ждать, пока Twisted deferred не вернет значение

У меня есть программа, которая извлекает информацию с других страниц и анализирует их с помощью BeautifulSoup и Twisted getPage. Позже в программе я печатаю информацию, созданную отложенным процессом. В настоящее время моя программа пытается распечатать его до того, как разница вернет информацию. Как мне заставить его подождать?

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

person Jody S    schedule 15.08.2010    source источник
comment
вы действительно используете 1 пробел для отступа ...   -  person Steven Sproat    schedule 15.08.2010
comment
Здесь была проблема с форматированием, в фактическом коде используется вкладка   -  person Jody S    schedule 16.08.2010


Ответы (3)


Похоже, вы пытаетесь создать / запустить несколько реакторов. Все подключается к тому же реактору. Вот как использовать DeferredList, чтобы дождаться всего вашего обратные вызовы, чтобы закончить.

Также обратите внимание, что twisAmaz возвращает значение. Это значение передается через callbacks DeferredList и получается как value. Поскольку DeferredList сохраняет порядок вещей, которые в него помещены, вы можете связать индекс результатов с индексом ваших ISBN.

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()
person habnabit    schedule 15.08.2010

Еще один отличный способ сделать это - использовать @ defer.inlineCallbacks. Он позволяет писать асинхронный код как обычную последовательную функцию: http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html#inlineCallbacks

person Thomas Dignan    schedule 19.12.2012

Во-первых, вы не должны помещать response.stop () в свой отложенный метод, так как он убивает все.

Теперь в Twisted "Ожидание" запрещено. Чтобы распечатать результаты вашего обратного вызова, просто добавьте еще один обратный вызов после первого.

person Luc Stepniewski    schedule 15.08.2010
comment
Спасибо, Люк! Могу я спросить, куда должен идти response.stop ()? - person Jody S; 15.08.2010
comment
Когда я сказал, что не следует помещать response.stop (), я имел в виду не помещать его в первый отложенный код, так как он остановит все. Поэтому вы должны поместить его в последний отложенный (тот, который печатает результаты), где вы уверены, что хотите остановить свою программу. Просто примечание: вы должны использовать addCallbacks (method1, error_method) для выявления потенциальных ошибок. - person Luc Stepniewski; 16.08.2010
comment
См. Руководство по отложенному на twistedmatrix.com/documents/current/core/howto /, особенно раздел под названием «Обратные вызовы могут возвращать отложенные». - person Luc Stepniewski; 16.08.2010
comment
Хорошо спасибо! И единственная проблема, с которой я сейчас сталкиваюсь, заключается в том, что я обращаюсь к нескольким сайтам и пытаюсь распечатать данные в определенном порядке, поэтому, если у меня есть функция для каждого сайта, он может распечатать их не по порядку ... - person Jody S; 16.08.2010