Ответы пользователя по тегу Python
  • На 25 строчке при 2-ом повторении выдаёт NonType, почему и как поменять на int?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Не надо так делать. Метод append изменяет список (добавляет в него элемент) и не возвращает никакого значения (или, что то же самое, возвращает None). То есть в результате такой записи мы добавляем элемент в список, а дальше этот список моментально выкидываем на помойку.

    week[g] = week[g].append(subj[gm])
    Ответ написан
    Комментировать
  • Почему тг бот обрезает сообщение?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Ответ, который уже помечен галочкой, конечно же поможет решить данную конкретную проблему, но его яркий недостаток в том, что автор вопроса так и не поймёт, в чём же именно проблема состояла. А это очень важно понимать, так как с такой же проблемой можно столкнуться и в других ситуациях.

    Проблема заключается в том, что & является разделителем аргументов GET-запроса. На первом же & в тексте будет считаться, что значение параметра text закончилось, а дальше идёт следующий параметр.

    Чтобы этого не происходило, надо заменять & на %26. Пробел надо менять на +, + менять на %2B, и это далеко не всё, с чем можно столкнуться. В частности, символ # в некоторых применениях является ссылкой на якорь на странице, и http-клиент (например, браузер) не будет передавать в запросе ничего, начиная с этого символа, если его не заменить на %23.

    Чтобы это решить в данном случае, наиболее удобный способ - это передать параметры отдельным аргументом params метода requests.get, чтобы библиотека requests сама грамотно разрулила все необходимые замены. Но если это недоступно для решения какой-то другой задачи - искать как выполнить соответствующее преобразование надо по ключевым словам urlencode/urldecode.
    Ответ написан
    Комментировать
  • Бот должен при команде /photo сохранять присланное после команды фото в одну папку, а при /photo1 в другую?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Не надо внутри одной функции объявлять другую. Это не будет работать, вообще никак! Результатом будет дописывание в список хендлеров новых обработчиков, а так как условия в них уже описаны в других обработчиках, то эти никогда вызваны не будут.

    Также при такой записи "внутренний" обработчик будет создаваться каждый раз заново. Короче, вытащить на верхний уровень, дать им другие имена и никогда так больше не делать.

    В данном случае для решения задачи нужно использовать FSM. В telebot есть очень простая в использовании реализация FSM на основе вызовов register_next_step_handler пример.
    Ответ написан
  • Как вызвать exception еще раз после его срабатывания?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Зачем так сложно? Делаем цикл по числу попыток, как только получаем успешный результат - делаем break и завершаем цикл досрочно. Можно даже обернуть это в функцию, тогда в основном коде не будет всей этой магии с циклом, код будет выглядеть более наглядным.

    def get_data(Китай, max_attempts=MAX_ATTEMPTS_DEFAULT):
        for attempt in range(1, max_attempts+1):
            try:
                submit = requests.post(Китай).json()
            except requests.exceptions.ConnectionError:
                continue
            if submit['success']:
                return submit
        return {'success':false, 'error':'attempts exceeded'}
    Ответ написан
    Комментировать
  • Что сделать, чтобы bot ловил handler в отдельном файле?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Зачем импортировать dp из всех файлов без разбору? В реальности будет импортирован последний, остальные будут импортированы впустую. Потому что следующий from импортирует другой dp и по имени dp будет доступен уже другой объект из другого модуля.

    Объект dp надо создать один раз в одном месте. В принципе, можно потом его потенциально импортировать куда угодно.

    Если хочется некоторой модульной структуры, то можно сделать в каждом модуле функцию навроде register_all_handlers(dp) и в ней делать https://docs.aiogram.dev/en/latest/dispatcher/inde.... Соответственно, после импорта всех модулей с хендлерами можно вызвать эту функцию от всех модулей:

    Примерно так
    import menu_commands
    import admin_commands
    import message_handlers
    
    dp = создаём_свой_Dispatcher
    
    menu_commands.register_all_handlers(dp)
    admin_commands.register_all_handlers(dp)
    message_handlers.register_all_handlers(dp)
    Ответ написан
    Комментировать
  • Как решить проблему с заморозкой цикла на Python?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Надо просто понимать, что asyncio - это не многопоточность (хотя и указан этот тэг в вопросе). Это один процесс, который выполняет только одну задачу в каждый момент времени. И переключает он задачи только тогда, когда какая-то из них запускает операцию ввода-вывода или что-то ещё подобное (например, asyncio.sleep).

    Например, если мы сделаем запрос к базе данных (с асинхронной библиотекой работы с этой базой обязательно! например, вместо sqlite3 используем aiosqlite), то пока база данных думает над ответом, скрипт может переключиться к какой-то другой ожидающей выполнения задаче. Когда база ответит, то цикл событий (event loop) вернёт управление задаче, которая сделала запрос к базе.

    В приведённом примере кода есть два места, которые могут быть узкими:

    1. Функция logic может быть и объявлена async, но если она делает чисто вычислительные операции без ввода-вывода (асинхронного), то в процессе её работы никогда не будет переключения на цикл события и, как следствие, не будут выполняться другие задачи. Даже если их собственный ввод-вывод уже совершился и задачи могут быть продолжены.

    2. Сама работа с базой может также блокировать цикл событий.

    Например, пусть logic работает 10 секунд, а dbase.search_in_queue - 5 секунд, и обе они содержат только синхронный код. Тогда пока выполняется dbase.search_in_queue свои 5 секунд, не будет выполняться logic, и наоборот.
    Ответ написан
    Комментировать
  • Можно ли получить значение callback_data при реплае?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    По-моему, тут типичная попытка решить простую задачу дурацким способом.

    Пользователь получает сообшение с inline-кнопкой. Вот пусть он эту кнопку и нажмёт, а бот получит в callback_query_handler событие с callback_data и обработает. Зачем ещё какое-то цитирование?

    Или тут попытка в кнопке хранить данные, которые при цитировании ещё и якобы можно будет достать? Сама идея дурацкая. Если надо к сообщениям хранить какие-то данные, то их надо хранить в самом боте: в базе данных, в хранилище FSM, да хотя бы in memory в переменных.
    Ответ написан
    Комментировать
  • Не отправляются фотографии пользователю в библеотеке telebot, что делать?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Не надо выкладывать такую длинную простыню, в которой трудно что-либо найти...

    Ссылка https://photos.app.goo.gl/6LckVsFKRfKy9ANu6 не является прямой ссылкой на фотографию, да и страница, на которую эта ссылка делает редирект, не является фотографией.
    Ответ написан
  • Состояния в FSM срабатывают со второго раза. Как это исправить?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Как написано - так и работает. Делаем /start - получаем стейт choice и кнопки. Нажимаем "добавить задачу" - получаем стейт add_task и больше в этом обработчике ничего не делается! И только после второго нажатия срабатывает обработчик "добавить задачу" из стейта add_task.

    Правильно убрать вообще обработчик для choice и вместо этого указать условия вида state=choice непосредственно у всех обработчиков.
    Ответ написан
    1 комментарий
  • Как обслуживать юзеров по очереди телебот?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    У тебя глобальные urls_list, price_list. Перемести их в функцию sender, они всё равно при каждом её вызове должны инициализироваться заново. Именно это и вызывает сейчас проблемы.
    Ответ написан
    Комментировать
  • Как правильно спарсить характеристики с сайта и записать в отдельные колонки эксель?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Например, можно автоматически создавать колонки под недостающие параметры по мере анализа. Можно завести словарь, который отображает названия характеристик в номер колонки, если при парсинге страницы обнаружена новая характеристика, которой в словаре нет - добавлять новую запись со следующим номером колонки. При создании новой строчки в выходнойм файле по именам параметров определять их позиции в массиве и подставлять.

    Другой вариант: разные категории помещать на разные листы (в случае с csv писать в разные файлы, ну или перейти на xlsxwriter). В этом случае таблица будет не такой разреженной, что в некоторых случаях может быть более удобно удобно.
    Ответ написан
    Комментировать
  • Как перебрать всех пользователей, и узнать создателя беседы?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Telegram Bot API не предоставляет возможности получить список участников чата. Это можно сделать только с помощью клиентского API (его реализует, например, библиотека telethon).

    Однако если id пользователя известен (можно, например, отслеживать ботом сообщения о вступлениях в чат, запоминая всех, кто вошёл в чат после бота), можно проверить его роль в чате с помощь метода get_chat_member. Но основатель чата, очевидно, будет в нём всегда самым первым пользователем до любого бота.
    Ответ написан
    Комментировать
  • Как сгруппировать ip по /24?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Ошибка в том, что не надо в процессе итерации по списку удалять из него элементы. Результат может быть непредсказуем.

    И вообще, код какой-то безумный. Задачу можно решить в один цикл, примерно так:

    mask_dict = {}
    
    for i in test:
        mask = IPv4Network('{}/24'.format(i), strict = False)
        if mask in mask_dict:
            mask_dict[mask].append(i)
        else: 
            mask_dict[mask] = [i]
    Ответ написан
    2 комментария
  • Как узнать количество уникальных результатов random.shuffle?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Число перестановок списка длины n - это n! (факториал: n!=1*2*3*...*n). Это основы комбинаторики.

    Так что если надо просто число различных вариантов, то:

    math.factorial(len(our_list))
    Ответ написан
    Комментировать
  • Как ограничить частоту нажатий кнопки?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Очевидно, запоминать куда-нибудь время последнего нажатия на кнопку и сравнивать его при очередном нажатии. Можно также при нажатии на кнопку убирать/изменять клавиатуру, но пользователь может успевать иногда нажать на кнопку 2-3 раза до исчезновения/изменения кнопки.
    Ответ написан
    6 комментариев
  • Как проверить работает ли бот или нет?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Это невозможно - боты никак не могут общаться друг с другом.
    Ответ написан
  • Как в TeleBot сохранять сообщения пользователя в определенный момент его действий?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Используй декоратор bot.callback_query_handler.

    @bot.callback_query_handler(func=lambda call: True)
    def my_handler(call):
        # call.data - содермое callback_data кнопки
        # call.message - исходное сообщение с кнопкой
        # call.message.from_user - отправитель исходного сообщения
        # call.from_user - нажавший на кнопку пользователь
        # call.message.chat - чат, в котором всё происходит
    Ответ написан
    Комментировать
  • Как отправить документ больше 50-ти мегабайт?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    В боте (aiogram) надо сделать сохранение куда-то списка текущих запросов (chat_id - запрос). Также сделать обработчик сообщений с content_type видео, который будет получать видео от юзербота, находить по нему в списке запросов chat_id, в который затем отсылать видео по file_id.
    Ответ написан
    Комментировать
  • Где в моём коде ошибка?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    И не будет работать. После отправки сообщения "Вам есть 18?" в переменной message не появится нового сообщения. И вообще, надо привыкать, что боты работают по событиям. Нажатие на кнопку - это новое событие, которое сделает новый вызов обработчика.

    Для таких задач лучше использовать FSM пример https://github.com/eternnoir/pyTelegramBotAPI/blob...
    Ответ написан
    Комментировать
  • Из-за чего возникает ошибка и как исправить?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    При вызове all_stories происходит промотка StringIO на конец виртуального "файла", и второй запуск all_stories() получает пустой список. Тут же all_stories() вызывается каждый раз в get_storie заново.

    Проще с самого начала хранить тексты не в не StringIO, а в list:

    stories = ["История 1", "История 2"]
    stories.append("А также история 3")
    Ответ написан
    Комментировать