gnifajio
@gnifajio
Совершенствуюсь каждый день

Как вызвать асинхронную функцию внутри @app.route?

Написал асинхронный парсер, решил запилить к нему веб интерфейс.
Проблема в том, что @app.route синхронный, а мой парсер - нет.
Когда я пытаюсь сделать так:
from my_parse_lib import parse_function
@app.route('/', methods=['post', 'get'])
def index():
    data = await parse_function()
    return render_template('index.html', data=data)

То естественно получаю ошибку. Я установил flaskio, но когда я делаю так:
from my_parse_lib import parse_function
@app.route('/', methods=['post', 'get'])
async def index():
    data = await parse_function()
    return render_template('index.html', data=data)

# RuntimeError: This event loop is already running

Тоже получаю ошибку. Я пробовал модуль syncer, но навесив декоратор @sync на свою асинхронную функцию, получил ошибку:
RuntimeError: There is no current event loop in thread 'Thread-x (process_request_thread)'.

Мне нужен любой рабочий способ получить данные из асинхронной функции внутри @app.route, и вернуть их пользователю.

Прошу меня не пинать в комментариях, т.к. тут простите, я новичок можно считать. Я уже 3й день перерываю просторы интернета, но ни одно решение мне пока что не помогло. Задавал этот вопрос на stackoverflow, но уже 4й день тишина...
  • Вопрос задан
  • 158 просмотров
Решения вопроса 1
ramzis
@ramzis
FullStackOverflow
from flask import Flask
import aiohttp
import asyncio

app = Flask(__name__)

async def get_url(session, url):
    async with session.get(url) as resp:
        status = resp.status
        html = await resp.text()
        title = html[html.find('<title>')+7:html.find('</title>')]
    return {'status': status, 'title': title}

async def start():
    result = ''
    async with aiohttp.ClientSession() as session:
        tasks = []
        for i in range(1063500, 1063624):
            tasks.append(asyncio.create_task(get_url(session, f'https://qna.habr.com/q/{i}')))
        resp = await asyncio.gather(*tasks)
    for r in resp:
        if r["status"] == 200:
            result += f'<p>Статус: {r["status"]} title: {r["title"]}</p>'
    return result

@app.route('/')
async def index():
    result = await start()
    return result

if __name__ == '__main__':
    app.run()


Результат

Статус: 200 title: Не работает многопоточность? — Хабр Q&A

Статус: 200 title: Как связать данные из одной таблицы SQL? — Хабр Q&A

Статус: 200 title: Не получается сделать так, чтобы когда я писал !role @nick выдавалась роль. Чтобы я не писал, она выдаётся мне. И да, я чайник :)? — Хабр Q&A

Статус: 200 title: Как мне вернуть текст, отправленный боту (Telebot)? — Хабр Q&A

Статус: 200 title: Корректно ли использую lazy load? — Хабр Q&A

Статус: 200 title: Как сделать рабочими ссылки в селекте? — Хабр Q&A

Статус: 200 title: Как авторизоваться на сервисе проверки чеков? — Хабр Q&A

Статус: 200 title: Как воспроизвести видео YouTube при клике по стороннему элементу в 2021? — Хабр Q&A

Статус: 200 title: Почему Recoil для React не обновляет стейт? — Хабр Q&A

Статус: 200 title: Как сделать коллайдер для торуса(бублика) в юнити? — Хабр Q&A

Статус: 200 title: Как я могу встроить HTML редактор на сайт? — Хабр Q&A

Статус: 200 title: Как вывести переменную в шаблон tpl twig? — Хабр Q&A

Статус: 200 title: Нормально ли работает Android Studio и эмулятор на AMD Ryzen 5 3600? — Хабр Q&A

Статус: 200 title: Распознавание цветов, как распознать разноцветные буквы на разноцветном фоне в Python? — Хабр Q&A

Статус: 200 title: Парсинг или скрапинг? — Хабр Q&A

Статус: 200 title: Как отслеживать запросы? — Хабр Q&A

Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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