Я хотел бы использовать Скрученное неблокирование getPage метод в веб-приложении, но это чувствует себя довольно сложным для использования такой функции по сравнению с urlopen.
Это - пример того, что я пробую к achive:
def web_request(request):
response = urllib.urlopen('http://www.example.org')
return HttpResponse(len(response.read()))
Настолько трудно иметь что-то похожее с getPage?
В отношении неблокирующих операций (которые вам явно нужны) нужно понимать, что вы не можете писать с ними последовательный код. Операции не блокируются, потому что не ждут результата. Они запускают операцию и возвращают управление вашей функции. Итак, 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
.
Я недавно отправил ответ на аналогичный вопрос , который предоставляет минимальное количество кода, необходимого для получения содержимого с 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 событие в этом случае).