Синхронные вызовы API с использованием Tornado, Python - PullRequest
0 голосов
/ 10 апреля 2020

После выхода Tornado 5 мы не можем использовать синхронный HTTPClient во время работы IOL oop. Вместо этого нам пришлось бы использовать AsyncHTTPClient.

Поэтому, может кто-нибудь мне помочь, показав мне, как я могу выполнять синхронные вызовы API с помощью AsyncHTTPClient в Tornado (Python веб-инфраструктура), который использует asyn c и жду вместо старых традиционных методов yield.

Я пытался реализовать его таким образом, и получал несколько ошибок.

class IndexHandler(tornado.web.RequestHandler):
    async def get_result(self, query):
        client = tornado.httpclient.AsyncHTTPClient()
        return await client.fetch("https://pokeapi.co/api/v2/pokemon/" + urllib.parse.urlencode(query))

    def get(self):
        q = self.get_argument('q')
        query = {'q': q}

        loop = asyncio.get_event_loop()
        response = loop.run_until_complete(self.get_result(query))
        loop.close()

        #response = client.fetch("https://pokeapi.co/api/v2/pokemon/" + urllib.parse.urlencode(query))
        #self.on_response(response)
        if response == "Not Found":
            self.write("Invalid Input")
            response_data = json.loads(response.body)
            pikachu_name = response_data['name']
            pikachu_order = response_data['order']
            self.write("""
                Pickachu Name: %s <br>
                Pickachu Order: %d <br>
                """ %(pikachu_name, pikachu_order))

Но, к сожалению, я получал много ошибок.

[E 200410 02:40:48 web:1792] Uncaught exception GET /?q=pikachu (::1)
    HTTPServerRequest(protocol='http', host='localhost:8000', method='GET', uri='/?q=pikachu', version='HTTP/1.1', remote_ip='::1')
    Traceback (most recent call last):
      File "C:\Python\Python37\lib\site-packages\tornado\web.py", line 1701, in _execute
        result = method(*self.path_args, **self.path_kwargs)
      File "C:\Users\Bagga\Documents\tornado\Tweet Rate\handlers.py", line 25, in get
        response = loop.run_until_complete(self.get_result(query))
      File "C:\Python\Python37\lib\asyncio\base_events.py", line 571, in run_until_complete
        self.run_forever()
      File "C:\Python\Python37\lib\asyncio\base_events.py", line 526, in run_forever
        raise RuntimeError('This event loop is already running')
    RuntimeError: This event loop is already running
[E 200410 02:40:48 web:2250] 500 GET /?q=pikachu (::1) 3.33ms
[E 200410 02:40:49 base_events:1608] Task exception was never retrieved
    future: <Task finished coro=<IndexHandler.get_result() done, defined at C:\Users\Bagga\Documents\tornado\Tweet Rate\handlers.py:16> exception=HTTP 404: Not Found>
    Traceback (most recent call last):
      File "C:\Users\Bagga\Documents\tornado\Tweet Rate\handlers.py", line 18, in get_result
        return await client.fetch("https://pokeapi.co/api/v2/pokemon/" + urllib.parse.urlencode(query))
    tornado.httpclient.HTTPClientError: HTTP 404: Not Found

1 Ответ

1 голос
/ 10 апреля 2020

Я думаю, что есть некоторая путаница относительно того, что запрос synchronous; синхронный запрос blocks выполнения программы (и, следовательно, всего IOLoop), прежде чем он сможет return получить результат; обычно это , а не , что вы хотите.
Запрос asynchronous возвращается до его завершения; он возвращает объекты-заполнители (Futures), которые обычно преобразуются в результат с ключевыми словами await или yield.

Я думаю, что вы ищете способ wait для выполнения запроса к API, который, как указано выше, выполняется с await или yield .

class IndexHandler(tornado.web.RequestHandler):
    async def get_result(self, query):
        client = tornado.httpclient.AsyncHTTPClient()
        response = await client.fetch("https://pokeapi.co/api/v2/pokemon/" + urllib.parse.urlencode(query))
        return response.body

    async def get(self):
        q = self.get_argument('q')
        query = {'q': q}
        response = await self.get_result(query)
        if response == b"Not Found":
            self.write("Invalid Input")
        else:
            response_data = json.loads(response.body)
            pikachu_name = response_data['name']
            ...

Обратите внимание на

async def get(self):

и

response = await self.get_result(query)

бит.

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