Задать вопрос
  • Как исправить проблему при выгрузке телеграмм бота на pyTelegramBotAPI на сервера?

    @codingoleg
    Вам же ошибка явно указала, что
    make sure that only one bot instance is running
    Бот с таким токеном уже запущен, поэтому второй не запустится. Остановите работающего бота или создайте новый токен и запустите ваш код с ним.
    Ответ написан
    Комментировать
  • Как вызвать функцию, чтобы код (бот) продолжал работу?

    @codingoleg
    Пример работы на aiogram 2.25. После нажатия /long_task можно нажимать как /start, так и /long_task (запустится еще одна корутина). Также в параметрах executor.start_polling() есть loop, куда можно добавить задачи по крайней мере при старте бота, например, планировщик.
    import asyncio
    import os
    from aiogram import Bot, Dispatcher
    from aiogram.types import Message
    from aiogram.utils import executor
    
    bot = Bot(token=os.environ['token'])
    dp = Dispatcher(bot)
    
    async def long_task():
        for i in range(10):
            print(i)
            await asyncio.sleep(1)
    
    @dp.message_handler(commands=['start'])
    async def dp_start(message: Message):
        await message.answer('Test')
    
    @dp.message_handler(commands=['long_task'])
    async def run_long_task(message: Message):
        print('Старт')
        await long_task()  # Функция, которая долго исполняется
        print('Финиш')
    
    if __name__ == '__main__':
        executor.start_polling(dp, skip_updates=True)
    Ответ написан
  • Как сделать асинхронность в процессах?

    @codingoleg
    Нужны асихронные библиотеки aiogram / pyrogram + schedule / APScheduler. Вот пример на aiogram 2.25 + schedule . Возможно, слегка костыль, но работает. Между выводом 'Старт' и 'Финиш' бот продолжает отзываться на команду /start.
    import asyncio
    import os
    import schedule
    from aiogram import Bot, Dispatcher
    from aiogram.types import Message
    from aiogram.utils import executor
    
    bot = Bot(token=os.environ['token'])
    dp = Dispatcher(bot)
    
    @dp.message_handler(commands=['start'])
    async def dp_start(message: Message):
        await message.answer('Test')
    
    async def run_schedule():
        while True:
            schedule.run_pending()
            await asyncio.sleep(1)  # Раз в секунду проверяем, не настал ли момент выполнять задание
    
    async def long_task():
        print('Старт')
        await asyncio.sleep(10)  # Функция, которая долго исполняется
        print('Финиш')
    
    def do_task():
        asyncio.ensure_future(long_task())
    
    if __name__ == '__main__':
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.create_task(run_schedule())  # Добавляем планировщик в петлю
        # schedule.every(15).seconds.do(do_task)  # Тестовый вариант каждые 15 секунд
        schedule.every(5).minutes.do(do_task)
        executor.start_polling(dp, loop=loop, skip_updates=True)  # Добавляем петлю к боту и запускаем его
    Ответ написан
    Комментировать
  • Почему переменной select_folder не присваивается значение?

    @codingoleg
    Вы не указали код, где создаете экземпляр класса MainWindow и вызываете метод create_button или что там у вас происходит, поэтому ответить невозможно.
    Ответ написан
    Комментировать
  • Как сделать правильный порядок отображения?

    @codingoleg
    from collections import Counter
    
    user = ['one', 'one', 'one', 'four']
    glob = [('two',), ('two',), ('three',)]
    
    def combine(user, glob):
        suggestions_user = [item[0] for item in Counter(user).most_common()]
        suggestions_global = [item[0] for item in Counter(i[0] for i in glob).most_common()]
    
        return {
            'suggestions_user': suggestions_user,
            'suggestions_global': suggestions_global,
            'combined_suggestions': suggestions_user + suggestions_global
        }
    Ответ написан
    Комментировать
  • Как адаптировать динамичную клавиатуру под разные сообщения?

    @codingoleg
    Пример на aiogram 2.25. Вместо user_1 у вас будет message.from_user.id или callback.from_user.id. Вместо словаря - база данных:
    from aiogram import Bot, Dispatcher, executor, types
    from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
    
    bot = Bot('')
    dp = Dispatcher(bot)
    
    user_1 = {'orders': {'заказ 1', 'заказ 2', 'заказ 3'}}
    
    @dp.message_handler(commands=['start'])
    async def list_orders(message: types.Message):
        if user_1['orders']:
            for order in user_1['orders']:
                await message.answer(
                    text=order,
                    reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton('Удалить', callback_data='Удалить заказ'))
                )
        else:
            await message.answer("no orders.")
    
    @dp.callback_query_handler(text='Удалить заказ')
    async def delete_order(callback: types.CallbackQuery):
        await callback.answer()
        order = callback.message.text
        if order in user_1['orders']:
            user_1['orders'].remove(order)
            await callback.message.answer(text=f'{order} удален')
        else:
            await callback.message.answer(text=f'{order} не найден')
        print(user_1['orders'])  # Для проверки
    
    executor.start_polling(dp)
    Ответ написан
    Комментировать
  • Как вызвать Callback без inline клавиатуры?

    @codingoleg
    Если вопрос только в поп-ап уведомлении, то в апи телеграма написано, что метод только для Inline клавиатур. Поэтому aiogram вам ничем не поможет. Если нужна проверка входящих данных, то можно использовать один из или все три варианта: 1. Машина состояний. 2. Функция проверки в аргументах декоратора. 3. Middleware для более сложных случаев. Вот вам 1 и 2 вариант:
    from aiogram import Bot, Dispatcher, executor, types
    from aiogram.types import ReplyKeyboardMarkup
    from aiogram.contrib.fsm_storage.memory import MemoryStorage
    
    bot = Bot('')
    storage = MemoryStorage()
    dp = Dispatcher(bot, storage=MemoryStorage())
    
    state_time = 'setTime'
    kb = ReplyKeyboardMarkup(row_width=10, one_time_keyboard=True)
    btns = (types.KeyboardButton(str(btn)) for btn in range(1, 31))
    kb.add(*btns)
    
    @dp.message_handler(commands=['start'])
    async def dp_choose_user(message: types.Message):
        await message.answer('Введите день:', reply_markup=kb)
        await dp.current_state().set_state(state_time)  # Вход в состояние ввода даты
    
    @dp.message_handler(lambda message: message.text.isdigit() and 1 <= int(message.text) <= 30, state=state_time)
    async def dp_choose_action(message: types.Message):
        await message.answer(text=f'Вы выбрали {message.text}')
        await dp.current_state().reset_state()  # Выход из состояния ввода даты
    
    @dp.message_handler(state=state_time)
    async def dp_choose_action(message: types.Message):
        await message.answer(text='Ошибка ввода даты. Введите еще раз.', reply_markup=kb)
    
    executor.start_polling(dp)
    Ответ написан
    Комментировать
  • Почему не проходит код для решения задачи на leetcode?

    @codingoleg
    Потому что 'list' object has no attribute 'split'. Рекомендую ознакомиться с типами данных и их методами. Выход из функции с любым количеством циклов осуществляется через return.
    Ответ написан
  • Как Python и Selenium заставить найти текст?

    @codingoleg
    Попробуй искать по xpath, а не по ID. Тогда точно найдешь.
    Ответ написан
    Комментировать
  • Не правильная проверка ячейки таблицы через цикл, почему не записывается переменная?

    @codingoleg
    fetchall и fetchone возвращают список кортежей. Поэтому el[3] - это тоже tuple, а не int. Нужное значение внутри должно быть, например, el[3][0].
    Ответ написан
    Комментировать
  • Почему callback_query_handler не видит call.data?

    @codingoleg
    Не понятно, на какой библиотеке вы это делаете. Вот вам пример на aiogram 2.25. Думаю, в остальных будет примерно так же, кроме добавленных слов async/await. Сделал по вашему шаблону, но лучше хэндлер с callback разделить на несколько, если их планируется много. Рекомендую ознакомиться, чем отличается types.Message от types.CallbackQuery, а также message_handler от callback_query_handler, чтобы в будущем не было проблем.
    from aiogram import Bot, Dispatcher, executor, types
    
    bot = Bot('token')
    dp = Dispatcher(bot)
    
    @dp.message_handler(commands=['start'])
    async def get_phone(message: types.Message):
        keyboard = types.InlineKeyboardMarkup()
        key_1 = types.InlineKeyboardButton(text='button 1', callback_data='b1')
        keyboard.add(key_1)
        key_2 = types.InlineKeyboardButton(text='button 2', callback_data='b2')
        keyboard.add(key_2)
        await bot.send_message(message.from_user.id, text='Выберите, нажав одну из кнопок:', reply_markup=keyboard)
    
    @dp.callback_query_handler(lambda call: True)
    async def get_storage(callback: types.CallbackQuery):
        if callback.data == 'b1':
            await callback.message.answer('Вы нажали на button 1')
        if callback.data == 'b2':
            await callback.message.answer('Вы нажали на button 2')
    
        # Заглушка, чтобы кнопка не мигала после нажатия
        await callback.answer()
    
    executor.start_polling(dp)
    Ответ написан
    1 комментарий
  • Почему код может не работать?

    @codingoleg
    Не знаю, как вы это написали, но у меня весь код подсвечивает ошибками на версии 2.25 или 3.*. У вас мешанина из разных клавиатур и переменных. Также я бы не стал в одном хэндлере содержать несколько условий - проще их разнести. Вот вам готовый код, но не знаю, как вы дальше сможете. Ответом на выбор жанра должна быть уже функция с @dp.callback_query_handler(), а не @dp.message_handler, из-за того, что клавиатура инлайн.
    @dp.message_handler(text='Выбрать фильм')
    async def Vibr(message: types.Message):
        markups = types.ReplyKeyboardMarkup(one_time_keyboard=True)
        markups.add(types.KeyboardButton('Жанр'))
        await message.answer(f'Хорошо, давай выберем!', reply_markup=markups)
    
    @dp.message_handler(text='Жанр')
    async def choose_genre(message: types.Message):
        markupt = types.InlineKeyboardMarkup()
        for genre in ('Комедия', 'Приключения', 'Драма', 'Фэнтези'):
            markupt.add(types.InlineKeyboardButton(genre, callback_data=genre))
        await message.answer(f'Выбери жанр!', reply_markup=markupt)
    Ответ написан
    Комментировать
  • Как работает этот бот?

    @codingoleg
    Причём тут бот? Это приложение телеги открывает твой список каналов. ID человека можно легко брать через Telegram bot api.
    Ответ написан
    Комментировать
  • Как использовать одинаковые данные в разных хендлерах?

    @codingoleg
    1. Глобальные переменные (если не пугает потеря данных).
    2. База данных.
    Ответ написан
    Комментировать
  • Как отправлять список частями в Телеграм-боте?

    @codingoleg
    Не совсем понятно, в чем проблема. У тебя код и так выводит по 3 элемента после ввода 'go'.
    x = ['a', 'b', 'c', 'd', 'e', 'w', 'df', 'ww', 'x', 'qa', 'wsx']
    
    for i in range(0, len(x), 3):
        input('Введи "go" ')
        print(x[i: i + 3])
    print('Выход из цикла')

    В телеграм-боте скорее всего будет реализовано по-другому - рекурсивным вызовом хэндлера, пока список себя не исчерпает. Но большей информации нет.
    Ответ написан
    1 комментарий
  • В чем я ошибся в решении задачи VK EDUCATION?

    @codingoleg
    Ваше решение технически верное, но имеет 2 недостатка, особенно для больших массивов и/или частых операций.
    Во-первых, вы создаёте копию массива для итерации (arr[::-1]), который занимает памяти столько же, сколько оригинальный массив. Во-вторых, вы удаляете элементы из массива по значению (remove), а не по индексу (del), что существенно замедляет выполнение. Рекомендую ознакомиться, как массив устроен под капотом и временную сложность добавления, вставки, изменения и удаления в него. Отсюда также будет понятно, почему одновременная итерация в прямом порядке с помощью цикла for и удаление элементов из массива - это плохая идея. Вот вам 4 функции с бенчмарками, из которых первая ваша:
    import random
    import time
    
    
    def func(arr, el):
        for i in arr[::-1]:
            if i == el:
                arr.remove(el)
        return len(arr)
    
    
    def remove_reverse(arr, el):
        for i in reversed(arr):
            if i == el:
                arr.remove(el)
        return len(arr)
    
    
    def del_by_index_reverse(arr, el):
        for i in reversed(range(len(arr))):
            if arr[i] == el:
                del arr[i]
        return len(arr)
    
    
    def del_by_index_while(arr, el):
        i = 0
        while i < len(arr):
            if arr[i] == el:
                # Удаляем значение по индексу и не сдвигаем указатель i
                del arr[i]
            else:
                i += 1
        return len(arr)
    
    
    # Создаем массив из 100000 случайных цифр от 0 до 9 и сделаем по копии для каждой функции
    arr1 = [random.randint(0, 9) for num in range(100_000)]
    arr2 = arr1[:]
    arr3 = arr1[:]
    arr4 = arr1[:]
    el = 5
    
    start = time.perf_counter()
    print(func(arr1, el))
    print(time.perf_counter() - start)
    
    start = time.perf_counter()
    print(remove_reverse(arr2, el))
    print(time.perf_counter() - start)
    
    start = time.perf_counter()
    print(del_by_index_reverse(arr3, el))
    print(time.perf_counter() - start)
    
    start = time.perf_counter()
    print(del_by_index_while(arr4, el))
    print(time.perf_counter() - start)
    Ответ написан
    Комментировать
  • Почему бот не отправляет сообщение в нужно время?

    @codingoleg
    Ты хочешь, чтобы у тебя было 2 параллельных процесса - работа бота и планировщик. Я это делал через aiogram/asyncio. Иначе будет работать либо одно, либо другое. Возможно ли это сделать через субпроцессы или многопоточность - хз.
    Ответ написан
    Комментировать
  • Как решить проблему с подключение к одной и той же таблице через Django orm и SQLAlchemy?

    @codingoleg
    Возможно, дело в асинхронности и race condition. Попробуй сделать функции обычными и проверь, будет ли ошибка.
    Ответ написан
    Комментировать
  • Как реализовать чтение входящих писем outlook.com с помощью python?

    @codingoleg
    Я бы использовал какую-нибудь библиотеку SMTP вместе с API почтового сервиса.
    Ответ написан
    Комментировать