Как перенести асинхронные вызовы с движка приложения на торнадо? - PullRequest
1 голос
/ 10 ноября 2011

Пример асинхронного движка приложения:

from google.appengine.api import urlfetch

rpc = urlfetch.create_rpc()
urlfetch.make_fetch_call(rpc, "http://www.google.com/")

try:
    result = rpc.get_result()
    if result.status_code == 200:
        text = result.content
        # ...
except urlfetch.DownloadError:
    raise
return text

Как мне это сделать в торнадо? Я пытался (используя swirl ) что-то вроде:

import swirl

http = tornado.httpclient.AsyncHTTPClient()
uri = 'http://www.google.com/'

try:
    response = yield lambda cb: http.fetch(uri, cb)
    if response.code == 200:
        text = result.content
        # ...
except tornado.httpclient.HTTPError:
    raise
return text

Но я получаю синтаксическую ошибку, потому что не могу получить возврат и выход в одной и той же функции ...

Ответы [ 2 ]

0 голосов
/ 02 сентября 2017

Если у вас есть Торнадо RequestHandler, помеченный декоратором @gen.coroutine, вы можете использовать Future s и ключевое слово yield, чтобы выполнить то, что вы хотите.

Для простого случая возврата результата асинхронной выборки HTTP достаточно метода AsyncHTTPClient.fetch:

class MainHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        def handle_response(response):
            if response.error:
                print("Error: %s" % response.error)
            else:
                self.write(response.body)

        http_client = AsyncHTTPClient()
        yield http_client.fetch('http://www.google.com/', handle_response)

Чтобы создать функцию, которая асинхронно возвращает произвольный результат, вам нужно создать собственный объект Future для возврата вызывающей стороне. Допустим, ваша функция должна выполнить асинхронную веб-выборку перед возвратом пользовательского значения:

def get_async_result():
    future = Future()

    def handle_response(response):
        if response.error:
            future.set_exception(Exception("Yikes"))
        else:
            future.set_result("I, for one, welcome our new robot overlords.")
    http_client = AsyncHTTPClient()
    http_client.fetch('http://www.google.com/', handle_response)
    return future

class MainHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        result = yield get_async_result()
        print result    # "I, for one, welcome our new robot overlords."
        # rest of handler here...

Оператор yield в вашем RequestHandler логически блокируется до тех пор, пока не будет завершен возвращенный Future, предоставляя вам результат (или исключение) напрямую.

(Обратите внимание, что как описано здесь , вы не можете использовать асинхронные механизмы Tornado в Google App Engine.)

0 голосов
/ 10 ноября 2011

Похоже, что вихрь не предоставляет никаких средств для возврата значений из сопрограмм.Другие структуры, использующие этот шаблон, такие как NDB, позволяют вызывать специальное возвращаемое исключение или возвращать возвращаемое значение, но, похоже, swirl не предоставляет эту опцию.Вам нужно будет реструктурировать свои сопрограммы, чтобы они не возвращали значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...