Задать вопрос
lexa_lashak
@lexa_lashak
Начинающий Python-разработчик

Как выполнять бесконечный цикл, чтобы он не блокировал работу всей программы?

Пишу телеграмм бота, который парсит данные с сайта (объявления). Сайт довольно часто обновляется, поэтому необходимо постоянно делать запросы на сайт: "не прилетело ли новое объявление"?
Собственно, поэтому было принято решение обернуть эти запросы в бесконечный цикл. Написав пару декораторов и один бесконечный цикл для обработки сообщений, я понял, (естественно) при этом скрипт само собой не может выполнить декораторы обработки входящих сообщений, тк висит в цикле.
Скрипт пишу на python с асинхронной библиотекой aiogram (изначально думал что она мне как-то поможет).

Вопрос состоит в следующем: как можно распараллелить данные процессы, чтобы и обновления отслеживать, и при этом обрабатывать входящие сообщения

ЗЫ: бота переписываю уже не первый раз, пытался найти ответ сам, хотел сюда прикрутить потоки или процессы, но не могу понять что в моем случае оптимальнее раз на то пошло, и как это правильно обыграть?
цикл в коде просто для отладки, ровно как и print в этом цикле
spoiler
import config
import aiogram
from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = config.token

# Инициализация бота и диспетчера
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)


#------------------------Цикл ---------------------------------------------------------------
#Будущий парсер
while 1:
    print('цикл')

#------------------------Блок обработки входящих сообщений------------------------------
@dp.message_handler(commands=['start']) #Приветствие
async def echo(message: types.Message):
    await message.answer('''Здравствуйте Вы подключились к боту . Чтобы узнать возможности Бота введите команду /help''')

@dp.message_handler(commands=['help']) #Помощь
async def echo(message: types.Message):
    await message.answer('help')

@dp.message_handler(commands=['add']) #Функция добавления фильтра
async def echo(message: types.Message):
    await message.answer('add')




if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)
  • Вопрос задан
  • 3863 просмотра
Подписаться 2 Средний 2 комментария
Решения вопроса 1
ediboba
@ediboba
сделать что-то похожее. Параллелите две таски в лупе
import asyncio
import datetime
import random


async def my_sleep_func():
    await asyncio.sleep(random.randint(0, 5))


async def display_date(num, loop):
    end_time = loop.time() + 50.0
    while True:
        print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
        if (loop.time() + 1.0) >= end_time:
            break
        await my_sleep_func()


loop = asyncio.get_event_loop()

asyncio.ensure_future(display_date(1, loop))
asyncio.ensure_future(display_date(2, loop))

loop.run_forever()
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
hottabxp
@hottabxp Куратор тега Python
Сначала мы жили бедно, а потом нас обокрали..
Я делал похожего бота для этого сайта(для получения новых вопросов по моим тегам). Алгоритм работы был примерно таким:
1) Создал функцию, которая загружает и парсит главную страницу этого сайта. Вытаскивает из нее все ссылки на новые вопросы. Функция возвращает список ссылок.
2) В цикле for беру каждую ссылку, и проверяю - есть ли она в файле(можно БД прикрутить). Если данной ссылки нет - значит вопрос новый. Добавляю ссылку в файл, и отправляю её себе в телеграм. Если ссылка в файле есть, значит этот вопрос уже отправлялся мне в телеграм, и, следовательно, - ничего не делаю
3) В боте делал цикл с задержкой 5 минут, и в цикле вызывал функцию-парсер.
5e57a5a5d8f6b747820507.png
Ответ написан
Создай поток
Ответ написан
@Pionchik
Попробуй BackgroundScheduler конкретно для функции, в которой у тебя будет цикл.

документация: https://apscheduler.readthedocs.io/en/3.x/userguid...
вот пример кода: https://github.com/agronholm/apscheduler/blob/3.x/...

вот пример для твоего кода:

from apscheduler.schedulers.background import BackgroundScheduler

def loop():
while 1: #цикл тут необязательный, так как таймер запускает print('цикл') каждые 10 секунд
print('цикл')

.....блок обработки входящих сообщений....

if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.add_job(loop, 'interval', seconds=10)
scheduler.start()
bot.polling(none_stop=True, interval=0)
Ответ написан
Ваш ответ на вопрос

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

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