Использовать getPage Twisted в качестве urlopen?

Я хотел бы использовать Скрученное неблокирование getPage метод в веб-приложении, но это чувствует себя довольно сложным для использования такой функции по сравнению с urlopen.

Это - пример того, что я пробую к achive:

def web_request(request):
   response = urllib.urlopen('http://www.example.org')
   return HttpResponse(len(response.read()))

Настолько трудно иметь что-то похожее с getPage?

5
задан RadiantHex 27 April 2010 в 12:52
поделиться

2 ответа

В отношении неблокирующих операций (которые вам явно нужны) нужно понимать, что вы не можете писать с ними последовательный код. Операции не блокируются, потому что не ждут результата. Они запускают операцию и возвращают управление вашей функции. Итак, getPage не возвращает файловый объект, который вы можете читать, как urllib.urlopen . И даже если бы это было так, вы не могли бы читать из него, пока данные не станут доступными (или он будет заблокирован). И поэтому вы не можете вызвать для него len () , поскольку он должен прочитать все сначала данные (которые заблокируют.)

В Twisted можно работать с неблокирующими операциями с помощью Deferreds , которые являются объектами для управления обратными вызовами. getPage возвращает Deferred , что означает «вы получите этот результат позже». Вы не можете ничего сделать с результатом, пока не получите его, поэтому вы добавляете обратных вызовов к Deferred , а Deferred будет вызывать эти обратные вызовы, когда результат доступно . Затем этот обратный вызов может делать то, что вы хотите:

def web_request(request)
    def callback(data):
        HttpResponse(len(data))
    d = getPage("http://www.example.org")
    d.addCallback(callback)
    return d

Дополнительная проблема с вашим примером заключается в том, что ваша функция web_request сама блокирует. Что вы хотите сделать, ожидая, пока станет доступен результат getPage ? Сделайте что-нибудь еще в web_request или просто подождите? Или вы хотите сделать сам web_request неблокирующим? Если да, то как вы хотите добиться результата? (Очевидный выбор в Twisted - вернуть еще один Deferred - или даже тот же, что и getPage , как в приведенном выше примере. Это не всегда подходит, если вы написание кода в другом фреймворке.)

Существует способ писать последовательный код с использованием Deferreds , хотя он несколько ограничен, труднее отлаживать, и основные люди Twisted плачут, когда вы используете его: twisted.internet.defer.inlineCallbacks . Он использует новую функцию генератора в Python 2.5, где вы можете отправлять данные в генератор, и код будет выглядеть примерно так:

@defer.inlineCallbacks
def web_request(request)
    data = yield getPage("http://www.example.org")
    HttpResponse(len(data))

Как и в примере, который явно возвратил d Deferred, это будет работать, только если вызывающий ожидает web_request должен быть неблокирующим - декоратор defer.inlineCallbacks превращает генератор в функцию, которая возвращает Deferred .

20
ответ дан 18 December 2019 в 06:34
поделиться

Я недавно отправил ответ на аналогичный вопрос , который предоставляет минимальное количество кода, необходимого для получения содержимого с URL-адреса с помощью getPage . Вот это для полноты:

from twisted.web.client import getPage
from twisted.internet import reactor

url = 'http://aol.com'

def print_and_stop(output):
    print output
    if reactor.running:
       reactor.stop()

if __name__ == '__main__':
    print 'fetching', url
    d = getPage(url)
    d.addCallback(print_and_stop)
    reactor.run()

Имейте в виду, что вам, вероятно, понадобится более глубокое понимание схемы реактора , используемой Twisted для обработки событий ( getPage firing being событие в этом случае).

4
ответ дан 18 December 2019 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: