Ответы пользователя по тегу Python
  • Как обрабатывать свои события?

    Я бы в первую очередь прибегнул к такому подходу, однако не могу утверждать, что call_later работает так как предполагается с такими временными рамками. Обычно использовал с временными рамками до 2 минут
    Пример кода
    import asyncio
    import concurrent.futures
    from datetime import datetime, timedelta
    import os
    import shutil
    
    
    def delete_func():
        # Удаление временных файлов и создание каталога заново
        shutil.rmtree('tempfiles/')
        print('Folder deleted')
        os.mkdir(path='tempfiles/')
        print('Folder created')
    
    
    def repeat_delete():
        _loop = asyncio.get_running_loop()
        with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
            # Выполнение функции delete_func в отдельном потоке
            _loop.run_in_executor(executor, delete_func)
        # Вычисляем время до 4 утра следующего дня
        now = datetime.now()
        tomorrow_4am = datetime(now.year, now.month, now.day) + timedelta(days=1, hours=4)
        delta = tomorrow_4am - now
    
        # Выполняем повторный запуск repeat_delete через вычисленное время
        _loop.call_later(delta.total_seconds(), repeat_delete)
    
    
    async def main():
        ...
    
    
    if __name__ == '__main__':
        # Создание нового цикла событий asyncio
        loop = asyncio.new_event_loop()
        # Вызов repeat_delete через 1 секунду
        loop.call_later(1, repeat_delete)
        # Запуск основной функции
        loop.run_until_complete(main())
    Ответ написан
    Комментировать
  • Автоматизация запроса по API в звуковую нейросеть из Excel через python?

    import os
    # import time
    
    import requests
    from openpyxl import load_workbook
    from dotenv import load_dotenv
    
    API_URL = 'https://api.edenai.run/v2/audio/text_to_speech'
    HEADERS = {"Authorization": f"Bearer {os.getenv('API_KEY')}"}
    DEFAULT_LANGUAGE = 'ru-RU'
    DEFAULT_OPTION = 'MALE'
    DEFAULT_VOICE = 'ru-RU_Alexei Syomin'
    
    
    def convert_text_to_speech(row_number: int, _id: int, text: str):
        payload = {
            'providers': 'lovoai',
            'language': DEFAULT_LANGUAGE,
            'option': DEFAULT_OPTION,
            'lovoai': DEFAULT_VOICE,
            'text': text
        }
    
        response = requests.post(API_URL, json=payload, headers=HEADERS)
        result = response.json()
    
        audio_url = result.get('lovoai', {}).get('audio_resource_url')
        if audio_url:
            audio_content = requests.get(audio_url).content
            with open(f'row_{row_number}_ID_{_id}.ogg', 'wb') as audio_file:
                audio_file.write(audio_content)
    
    
    def main(file_name: str):
        book = load_workbook(file_name)
        sheet = book.active
        for row in range(2, sheet.max_row + 1):
            _id = sheet[row][0].value
            text = sheet[row][1].value
            convert_text_to_speech(row, _id, text)
    
            # Установите задержку, если имеется ограничение на кол-во запросов в секунду
            # time.sleep(3)
    
    
    if __name__ == '__main__':
        load_dotenv()
        main('name.xlsx')
    Ответ написан
    3 комментария
  • FSMStorageWarning?

    При инициализации dispatcher нужно передать в него storage
    from aiogram import Bot, Dispatcher, types
    # from aiogram.contrib.fsm_storage.memory import MemoryStorage
    from aiogram.contrib.fsm_storage.redis import RedisStorage2
    
    storage = RedisStorage2()
    # storage = MemoryStorage()
    
    bot = Bot(token=c.tg_bot.token, parse_mode=types.ParseMode.HTML)
    dp = Dispatcher(bot, storage=storage)

    UPD. При использовании redis на windows рекомендую устанавливать Memurai, так как есть поддержка redis 6, в некоторых случаях это избавит вас от проблем при переносе кода на Unix системы
    Ответ написан
    Комментировать
  • Как подключить приватный прокси к яндекс музыке?

    Вы не указали протокол прокси. На гитхабе указаны следующие примеры
    Примеры proxy url:
    
    socks5://user:password@host:port
    http://host:port
    https://host:port
    http://user:password@host
    Ответ написан
    Комментировать
  • Telegram bot Как назначить время и уведомить через заданное время?

    По правилам ресурса код стоит выкладывать текстом, оборачивая тэгом code.
    Вам подойдут очереди сообщений (rq, Celery, queue, asyncio.Queue).
    Примитивно ставить задачу в цикл событий.
    P.S. Рекомендую очереди
    @dp.message_handler(commands=['some_command'])
    async def some_handler(message: Message):
        text = 'Текст для отправки '
        DELAY = 10
        _loop = asyncio.get_running_loop()
        _loop.call_later(DELAY, func, message.from_user.id, text)
    
    async def func(chat_id, text):
        await dp.bot.send_message(chat_id, text)

    UPD Рекомендации
    1. Избавьтесь от n = int(input()). Вызов input блокирует выполнение кода, как и time.sleep
    2. Ознакомьтесь с встроенной в aiogram машиной состояний (FSM). Меняя state отлавливайте введенное пользователем число.
    3. Избавьтесь от конструкции try: except: проверяя является ли message.text числом
    if message.text.isdigit():
        print('ok')
    else:
        print('Это не число')
    Ответ написан
    4 комментария
  • Как преобразовать такой список словарей в Python?

    Умножив d_list на 100.000 у меня выполнилось за 0.6868....
    Не знаю на сколько "быстрым" такой результат можно назвать
    Первый вариант
    res = []
    for dictionary in d_list:  # * 100_000:
        result_dict = {}
        for key in dictionary:
            if dictionary[key] is not None:
                result_dict[key] = dictionary[key]
        result_dict = {**result_dict, **{'qty1': False, 'fp1': False,
                                         'qty2': False, 'fp2': False,
                                         'qty3': False, 'fp3': False}}
        if isinstance(dictionary['b'], list):
            for z in range(1, len(dictionary['b']) - 1):
                result_dict[f'qty{z}'] = dictionary['b'][z - 1]['qty']
                result_dict[f'fp{z}'] = dictionary['b'][z - 1]['fp']
    
        res.append(result_dict)

    Если все таки вы не ожидаете в результате значение ключа b в исходном виде.
    Выполнилось за 0.3226
    UPD
    res = []
    for dictionary in d_list:  # * 100_000:
        result_dict = {'a': dictionary['a'],
                       'c': dictionary['c'],
                       'qty1': False, 'fp1': False,
                       'qty2': False, 'fp2': False,
                       'qty3': False, 'fp3': False
                       }
        if isinstance(dictionary['b'], list):
            for z in range(1, len(dictionary['b']) - 1):
                result_dict[f'qty{z}'] = dictionary['b'][z - 1]['qty']
                result_dict[f'fp{z}'] = dictionary['b'][z - 1]['fp']
    
        res.append(result_dict)
    Ответ написан
    1 комментарий
  • Как запустить асинхронную функцию по расписанию python?

    if __name__ == '__main__':
        loop = asyncio.new_event_loop()
        scheduler = AsyncIOScheduler(event_loop=loop)
        scheduler.add_job(main, 'interval', seconds=3)
        scheduler.start()
        try:
            loop.run_forever()
        except (KeyboardInterrupt, SystemExit):
            pass

    Описание проблемы. (Как я это понял)
    Пример из github репозитория библиотеки ошибочен по двум причинам
    вызывается функция start(), которая сама выполняет get_event_loop()
    После этого в текущем потоке создается цикл событий.
    Далее в примере эти строки
    try:
        asyncio.get_event_loop().run_forever()
    except (KeyboardInterrupt, SystemExit):
        pass
    в результате мы получаем второй запущенный цикл событий из-за чего мы получаем DeprecationWarning: There is no current event loop
    Ответ написан
    4 комментария
  • Как соединиться с mysql, используя SSL файл и флаг verify identity?

    import asyncio
    import ssl
    
    
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    # the root CA path is dependent on your system. 
    ctx.load_verify_locations(cafile='/etc/ssl/cert.pem')
    
    async def test_example(loop):
        pool = await aiomysql.create_pool(host='', port=3306, user='redst', password='',
                                      db='aiodb', loop=loop, ssl=ctx)
    Ответ написан
    Комментировать
  • Почему следующий код может иногда падать с 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")
    Ответ написан