Задать вопрос
  • Почему следующий код может иногда падать с runtime error?

    Код [запускался на Python 3.8, 3.9, 3.10]
    import asyncio
    import datetime
    import random
    import colorama
    
    
    async def main():
        t0 = datetime.datetime.now()
        print(colorama.Fore.WHITE + "App started.", flush=True)
    
        data = asyncio.Queue()
    
        task1 = asyncio.ensure_future(generate_data(20, data))
        task2 = asyncio.ensure_future(generate_data(20, data))
        task3 = asyncio.ensure_future(process_data(40, data))
        # Переименовано из "final_task" в "gather_result" т.к. gather возвращает результат (Список значений объектов)
        # В данном коде ничего не возвращается и можно удалить print и саму переменную
        gather_result = await asyncio.gather(task1, task2, task3)
        print(gather_result)
        dt = datetime.datetime.now() - t0
        print(colorama.Fore.WHITE + f"App exiting, total time: {dt.total_seconds():,.2f} sec.", flush=True)
    
    
    async def generate_data(num: int, data: asyncio.Queue):
        for idx in range(1, num + 1):
            item = idx * idx  # equal idx ** 2 
            await data.put((item, datetime.datetime.now()))
    
            print(colorama.Fore.YELLOW + f" -- generated item {idx}", flush=True)
            await asyncio.sleep(random.random() + 0.5)
    
    
    async def process_data(num: int, data: asyncio.Queue):
        processed = 0
        while processed < num:
            item = await data.get()
    
            processed += 1
            value = item[0]
            t = item[1]
            dt = datetime.datetime.now() - t
    
            print(colorama.Fore.CYAN + f" +++ Processed value {value} after {dt.total_seconds():,.2f} sec.", flush=True)
            await asyncio.sleep(0.5)
    
    
    if __name__ == '__main__':
        asyncio.run(main())

    Asyncio "Running Tasks Concurrently" gather
    asyncio.gather на русском
    Приведенный вами код актуален для Python 3.6 (Пункт 18.5.3.5.1. документации asyncio Python 3.6.15), но не для 3.7+
    Ответ написан
    1 комментарий
  • Почему возникает ошибка?

    Вы можете создать подобный класс.
    Пример реализации
    import asyncio
    import ssl
    from typing import Optional, Type
    
    import aiohttp
    import certifi
    import ujson as json
    
    
    class Scrapper:
        def __init__(self, connections_limit: int = None) -> None:
            self._session: Optional[aiohttp.ClientSession] = None
            self._connector_class: Type[aiohttp.TCPConnector] = aiohttp.TCPConnector
            ssl_context = ssl.create_default_context(cafile=certifi.where())
            self._connector_init = dict(limit=connections_limit, ssl=ssl_context)
    
        async def get_new_session(self) -> aiohttp.ClientSession:
            return aiohttp.ClientSession(
                connector=self._connector_class(**self._connector_init),
                json_serialize=json.dumps
            )
    
        async def get_session(self) -> Optional[aiohttp.ClientSession]:
            if self._session is None or self._session.closed:
                self._session = await self.get_new_session()
    
            if not self._session._loop.is_running():
                await self._session.close()
                self._session = await self.get_new_session()
            return self._session
    
        async def make_request(self, session, url, post, **kwargs):
            try:
                if post:
                    async with session.post(url, data=None, headers=None, **kwargs) as response:
                        try:
                            return await response.json()
                        except:
                            return response.text
                else:
                    async with session.get(url, params=None, headers=None, **kwargs) as response:
                        try:
                            return await response.json()
                        except:
                            return response.text
            except aiohttp.ClientError as e:
                print(f"aiohttp client throws an error: {e.__class__.__name__}: {e}")
    
        async def request(self, url: str, post: bool = False, **kwargs):
            return await self.make_request(await self.get_session(), url, post, **kwargs)
    
        async def get_access(self) -> None:
            return await self.request("https://google.com", False)
    
    
    scrapper = Scrapper()
    
    
    async def main():
        await scrapper.get_access()
    
    
    asyncio.run(main())
    Ответ написан
    Комментировать
  • Почему бот на aiogram молчит, пока выполняет действия?

    asyncio sleeping
    sleep() always suspends the current task, allowing other tasks to run.

    Наглядный пример выполнения
    Код
    import asyncio
    import time
    
    
    async def test(delay: int, number: int):
        print(f"Задача: {number}\n"
              f"Начато выполнение в {time.strftime('%X')}\n"
              f"Ждем {delay} секунд")
        await asyncio.sleep(delay)
        print(f"Закончили задачу {number} в {time.strftime('%X')}")
    
    
    async def startup():
        delays = [10, 8, 14, 5]
        for i, x in enumerate(delays):
            await test(x, i + 1)
    
    
    if __name__ == '__main__':
        asyncio.run(startup())

    Вывод
    Задача: 1
    Начато выполнение в 01:47:05
    Ждем 10 секунд
    Закончили задачу 1 в 01:47:15
    Задача: 2
    Начато выполнение в 01:47:15
    Ждем 8 секунд
    Закончили задачу 2 в 01:47:23
    Задача: 3
    Начато выполнение в 01:47:23
    Ждем 14 секунд
    Закончили задачу 3 в 01:47:37
    Задача: 4
    Начато выполнение в 01:47:37
    Ждем 5 секунд
    Закончили задачу 4 в 01:47:42

    Можете считать, что в данном случае await asyncio.sleep(delay) является блокирующей функцией
    Ответ написан
  • Как сделать так чтобы инлайн кнопки не дублировались aiogram?

    Кнопки у вас добавляются лишние потому что вы просто каждый раз добавляете в InlineKeyboardMarkup кнопку, а keyboard_bar_inline_tarif_buy_status у вас глобальная переменная
    Нужно вынести создание клавиатуры в отдельную функцию.
    Также логику как-то переработать обращения к бд и самих кнопок, текста и callback'а
    @dp.message_handler(lambda message: message.text == ' Мои покупки')
    async def buy_status(message : types.Message):
        await bot.send_message(message.from_user.id, f' Ваши купленные паки:', reply_markup=keyboard_bar_inline_tarif_buy_status(), parse_mode='Markdown')
        
    def keyboard_bar_inline_tarif_buy_status():
        kb = InlineKeyboardMarkup(row_width=1)
        for i in range(1, 7):
            cur.execute(f'SELECT TARIF{i} FROM users')
            data_total = cur.fetchone()
            if data_total[0] == 'PAID':
                kb.add(InlineKeyboardButton(text=f'{i}', callback_data=f'pay{i}'))
        return kb
    Ответ написан
    Комментировать
  • Как вернуться к первому состоянию в Aiogram?

    У команды start нет состояния
    await state.finish()
    Либо назначайте состояние ввода имени
    await state.set_state(reg.name)
    Но не забудьте, что у пользователя должна быть возможность выйти из состояния самостоятельно
    Ответ написан
    4 комментария
  • Как остановить цикл при вводе последующей команы AIOGRAM (Python)?

    Не надо использовать цикл while в асинхронном коде, да и в целом если бот рассчитан на более чем одного пользователя
    Используйте storage
    from aiogram.contrib.fsm_storage.memory import MemoryStorage
    
    storage = MemoryStorage()

    from aiogram.dispatcher import FSMContext
    
    @dp.message_handler(commands=['start'])
    async def start(message: types.Message,  state=FSMContext):
        await message.answer('Вы ввели команду /start, введите команду /stop или /cancel чтобы выйти из меню')
        await state.set_state(YourState.name_state)
    
    @dp.message_handler(commands=['stop'], state=YourState.name_state)
    async def stop(message: types.Message,  state=FSMContext):
        await message.answer('Вы ввели команду /stop')
        await state.finish()
    
    @dp.message_handler(commands=['cancel'], state='*')
    async def cancel(message: types.Message,  state=FSMContext):
        current_state = await state.get_state()
        if current_state is None:
            return
        await state.finish()
        await message.answer('Вы ввели команду /cancel')
    Ответ написан
    Комментировать
  • Как обновить таблицу SQLite нажатием inline кнопки в телеграм боте?

    Замените
    @dp.callback_query_handler(text='testit')
    На
    @dp.callback_query_handler(lambda c: c.data == 'testit')

    Ваш декоратор был правильным для отслеживания KeyboardButton, но не для InlineKeyboardButton
    Ответ написан
    Комментировать
  • Бот отправляет фото из директории в чат, как мне получить file_id что бы он не грузил каждый раз из папки?

    photo_data = await db.get_file_info(f'{files_dir}file_name.png')
    if photo_data is None:
        media = types.InputFile(f'{files_dir}file_name.png')
        msg = await dp.bot.send_photo(chat_id=message.chat.id, photo=media)
        full_size_photo_id = msg['photo'][-1]['file_id']
        await db.add_file_info(full_size_photo_id)
    else:
        await dp.bot.send_photo(chat_id=message.chat.id, photo=photo_data)


    В зависимости от того какую БД и используете вы fetchval или fetch возможно условие
    if photo_data is None:
    Надо будет поменять на:
    if len(photo_data) == 0:
    Ответ написан
    2 комментария
  • Как отправить фото aiogram python?

    from aiogram import types
    
    
    await bot.send_photo(admin_id, types.InputFile('путь к файлу'))
    Ответ написан
  • [AIOGRAM, SQLITE3] Как вывести всю базу одним сообщением?

    if adm_spis == spisbtns[0]:
        users = db.db_all()
        db_schet = len(users)
        users_list = {}
        text_message = ''
        for user in users:
            id = user[0]
            username = user[1]
            user_id = user[2]
            number = user[3]
            subscription = user[4]
            admi = user[5]
            blocked = user[6]
            ban = user[7]
            text_message += f'<b>ID: </b><code>{id}</code>\n<b>USERNAME: </b><code>{username}</code>\n<b>USER_ID: </b><code>{user_id}</code>\n<b>NUMBER: </b><code>{number}</code>\n<b>SUBSCRIPTION: </b><code>{subscription}</code>\n<b>BLOCKED: </b><code>{blocked}</code>\n<b>BAN: </b><code>{ban}</code>\n\n'
    
        await msg.answer(f'<b>ВСЯ БАЗА ДАННЫХ </b>\n\n<i>Всего в базе: </i><code>{db_schet}</code>\n\n{text_message}', parse_mode='html')


    Также в столбцах из которых вы берете переменные (subscription, admi, blocked, ban) можно изменить тип данных на bool для отображения False/True вместо 0/1 .

    Если в будущем рассматриваете более обширный доступ администратора к БД, посмотрите в сторону django с его админкой.
    Ответ написан
  • Бот принимает сообщения, но хендлер не работает, что делать?

    from aiogram import types
    
    @dp.message_handler(commands=['start'])
    async def start_command(message: types.Message):
        await message.answer("Hello")
    Ответ написан
  • Aiogram, как привоить значение State'у, до того как пользователь введёт значение после set()?

    Чтобы обращаться к данным в state, в функции прописываете:
    async def start_bot(message: types.Message, state: FSMContext):

    переменную state = dp.current_state(user=user_id) переименовываете, т.к. вы ею переназначаете FSMContext на dp.current_state(user=user_id)
    после этого await state.update_data(item_id=item_id) выполнится успешно
    Ответ написан
    Комментировать
  • Как сделать время ожидания ответа на вопрос Aiogram, с использованием State?

    @dp.message_handler(state=Add.test_state)
    @dp.message_handler(commands=['start'])
    async def start_bot(message: types.Message, state: FSMContext):
        if message.text == '/start':
            await message.answer(text="Отправь мне свое имя")
            await Add.test_state.set() # Ваш state
            await asyncio.sleep(5) # 5 сек спим
            try:
                data = await state.get_data()
                if data['get_name'] == 'true':
                    pass
            except KeyError: 
                # Если пользователь не ответил или за это время state завершился, получаем KeyError
                await message.answer(f'Жаль, что ты не ответил')
                await state.finish()
        else:
            await state.update_data(get_name='true')
            await message.answer(f'Твое имя {message.text}')
            # Установите следующие состояние
            # Если вы завершите состояние, то тогда бот ответит  'Жаль, что ты не ответил'


    Как отработало
    60f69e24ad752236650893.png
    Ответ написан
    2 комментария
  • Почему call.data не откликается?

    У вас хендлер @dp.callback_query_handler(text='rand') принимает text, который нужен для обычных кнопок, после нажатия которых отправляется сообщение от пользователя.

    Например вы можете это реализовать так:
    @dp.callback_query_handler(lambda c: c.data == 'amf')
    async def randws(call: CallbackQuery):
        await call.message.answer('gggg')


    Чтобы не создавать кучу хендлеров на каждый callback советую ознакомиться с callback_data_factory:
    Примеры:
    callback_data_factory_simple
    callback_data_factory
    Документация:
    callback_data
    Ответ написан
    Комментировать
  • Зачем нужен Dispather в Aiogram?

    Не стоит на столько углубляться на данном этапе изучения библиотеки.
    Если коротко Dispatcher принимает все апдейты и обрабатывает их.
    Можете отправлять сообщения как вам удобно, хоть await mybot.bot.send_sticker хоть await bot.send_sticker лишь бы импортировали все правильно
    Ответ написан
    Комментировать
  • Почему парсер ничего не выдаёт?

    Добавьте в headers ключ 'User-Agent'
    Например
    'User-Agent': 'PostmanRuntime/7.28.1'
    Пример кода
    import requests
    from bs4 import BeautifulSoup
    import lxml
    url = "https://www.ozon.ru/product/holodilnik-indesit-tia-180-belyy-277079362/"
    
    payload = {}
    headers = {
        'User-Agent': 'PostmanRuntime/7.28.1',
        'Cookie': 'ЗДЕСЬ КУКИ'}
    
    response = requests.request("GET", url, headers=headers, data=payload)
    
    page = BeautifulSoup(response.content, 'lxml')
    print(page)


    цену нашел только в этом элементе
    спойлер
    <div id="state-webPrice-836055-default-1"
    					data-state='{"isAvailable":true,"price":"17 990 ₽","originalPrice":"20 390 ₽","showOriginalPrice":true,"mode":"credit","payment":"1 799 ₽","paymentTerm":"12 мес","hintLink":"https:\u002F\u002Fwww.ozon.ru\u002Fsection\u002Fcredit\u002F","hintText":"Приблизительный расчет. Платеж зависит от срока и типа кредитного продукта"}'>
    Ответ написан
  • Как с помощью библиотеки aiogram сделать так, чтобы бот отправлял сообщение по вашему id?

    метод answer не принимает параметр chat_id
    используйте
    await mybot.bot.send_message(chat_id = 123, text=message.text)

    если передавать параметры по порядку, не обязательно указывать именованные параметры, вы можете сделать так:
    await mybot.bot.send_message(627976213, message.text)
    Ответ написан
    3 комментария
  • Не получив число после команды бот должен отправить сообщение?

    Исходя из вашего
    кода
    @dp.message_handler(commands=['number'])
    async def number(message: types.Message):
        number = message.get_args()
        number1 = int(number)*1000
        if int(number) < 0:
            await message.reply("Нельзя вводить отрицательное число")
        else:
            await message.reply(f"Твое число {number1}")
    который вы написали в комментарии, к ответу выше.

    Вам следует сделать проверку есть ли deeplink и является ли он числом

    Например
    @dp.message_handler(commands=['number'])
    async def number(message: types.Message):
        number = message.get_args()
        if number is not None and number.isdigit():
            if int(number) < 0:
                await message.reply("Нельзя вводить отрицательное число")
            else:
                await message.reply(f"Твое число {int(number) * 1000}")
        elif number is None:
            await message.reply(f'Введите число после команды "/number 5 "')
        else:
            await message.reply(f'После команды "/number" ожидается число, а не текст')

    Ответ написан
    Комментировать
  • Ошибка при распаковке Brotli?

    brotli.error: BrotliDecompress failed

    Вы можете не импортировать Brotli, т.к. urlib3 использующийся в requests сам выполняет то, что вам нужно с помощью Brotli, если он установлен
    Ответ написан
    1 комментарий
  • Как сделать чтобы бот отвечал на сообщения(reply)?

    Согласно документации вы должны использовать не from_id, а message_id

    reply_to – идентификатор сообщения, на которое требуется ответить.
    целое число, доступен начиная с версии 5.92


    message_id — идентификатор сообщения


    messages.send
    Ответ написан