Задать вопрос
  • Process finished with exit code 0 Telebot Python в чем ошибка?

    Vindicar
    @Vindicar
    RTFM!
    Отступы в питоне важны!
    У тебя всё, начиная с @client.event async def on_ready(): попало внутрь обработчика события.
    Как следствие, бот не стартует, пока не выполнится обработчик, а обработчик не выполнится, так как бот не стартовал. Программа доходит до конца, решает "ну, что сказали сделать - я сделала" и завершается нормально, т.е. с кодом 0.
    Сдвинь соответствующий участок кода (начиная с указанного) влево.
    Ответ написан
  • Каким образом запустить и провести калькуляции с файлом excel, не открывая excel?

    Vindicar
    @Vindicar
    RTFM!
    Использовать COM (в питоне это пакет comtypes, в других языках есть свои средства) чтобы обращаться к средствам автоматизации Excel. По сути, это то же самое апи, которое доступно через макросы или скрипты Visual Basic. Но это будет требовать установленного на машине Excel для работы. Так что это скорее костыль, чем решение.
    Ответ написан
    2 комментария
  • Почему input() не сохраняет значения в списке?

    Vindicar
    @Vindicar
    RTFM!
    input() не сохраняет значения в списке

    Всё оно сохраняет, просто вот эта строка - полная чушь.
    res_int = ''.join(i if i.isdigit() else ' ' for i in s).split()

    У тебя s - список строк. Ты заменяешь на пробелы все строки в списке, которые содержат что-то кроме цифр (а это все строки в твоём списке!), затем соединяешь строки в одну и делишь их по пробелу. Конечно, у тебя получится пустой список в итоге.
    У меня такое чувство, что этот код вообще предполагал, что в s будет одиночная строка, а не список - но даже тогда он не сделает что тебе надо.

    Нужно каждую строку в s разделить по символу "," и все элементы полученного списка, кроме нулевого, превратить в числа. Дальше уже будет просто.
    Ответ написан
  • Почему json файл не создается через python в docker?

    Vindicar
    @Vindicar
    RTFM!
    А где ты файл-то создаёшь? На подмонтированном volume? Или где попало?
    Вообще изменения в файловой системе контейнера не сохраняются при остановке. Тебе нужен volume (или иной похожий механизм), чтобы сохранить данные между перезапусками контейнера.
    Читай про docker persistence.
    Ответ написан
  • Как перевести блоки кода в SPA приложении?

    Vindicar
    @Vindicar
    RTFM!
    1. Регулярками выдернуть содержимое переменных
    2. Для поиска текстовых фрагментов можно использовать модуль xml.dom.pulldom, хотя тут может и BeautifulSoup справится.
    3. Фрагменты уже отправляешь в желаемый сервис переводчик. Возможно, стоит их отправлять группами с разделителем.
    4. Конструируешь итоговый код - хоть поиском-заменой, хоть постепенной записью нового XML. А может, сгенерируешь сразу код с поддержкой локализации, на будущее.
    Ответ написан
  • Как протестировать код как Я.Контест?

    Vindicar
    @Vindicar
    RTFM!
    Втупую - subprocess для запуска дочернего процесса с перехватом стандартного ввода вывода. А дальше какая-то база, содержащая набор пар "ввод - ожидаемый вывод" для скрипта.
    Веселье начнётся, когда ты поймёшь, что в запускаемом скрипте может быть всё, что угодно, и его надо выполнять в песочнице, где можно контролировать какие модули он импортирует.
    Ответ написан
  • Как реализовать отложенное сообщение?

    Vindicar
    @Vindicar
    RTFM!
    используй асинхронную библиотеку для бота. Асинхронные функции могут приостановить своё выполнение и отдать процессорное время другим, которые готовы выполняться. Тогда, как написали выше, всё решается вызовом asyncio.sleep(). Но это предполагает, что ты можешь бота переписать на асинхронный подход.

    Если же нет, придётся использовать потоки, в расчёте на то, что бот потокобезопасен.
    Ответ написан
  • Ошибка "cannot pickle '_tkinter.tkapp' object" при использовании Multiprocessing, почему?

    Vindicar
    @Vindicar
    RTFM!
    Потому что multiprocessing - это не магия, а инструмент с ограничениями.
    В частности, у каждого дочернего процесса полностью своя память. Никаких общих объектов! Любые данные, передающиеся между процессами, упаковываются встроенным модулем pickle, и распаковываются на той стороне. Как следствие, есть довольно ограниченный набор типов данных, которые можно передавать как аргумент, или возвращать как результат из другого процесса. Окна ткинтера в этот набор не входят, о чём тебе и сообщает ошибка.

    Используй пару multiprocessing.Queue или SimpleQueue для коммуникации с работающим процессом. Одна очередь должна содержать команды от главного процесса дочернему, а другая - оповещения от дочернего главному. Сосредоточь всю работу с GUI в главном процессе, а для периодической проверки наличия новых оповещений в очереди используй метод root.after().

    Ну и да, "принудительно остановить" - это вообще не лучшая идея, и не должно быть нормальным подходом. Перепиши свои функции так, чтобы они мониторили какой-нибудь multiprocessing.Event (ну или threading.Event, если хочешь работать в потоках), и останавливались, когда он окажется взведён.
    Ответ написан
    2 комментария
  • Построение игры в монетку с вариативностью и возможностью выбора на Python?

    Vindicar
    @Vindicar
    RTFM!
    Ошибки две. Первая, вместо двух отдельных if тебе нужна цепочка if-elif-else, а лучше - одна пара if-else с правильно написанным условием победы. Второе, ввод догадки пользователя должен быть ПЕРЕД проверкой, а не после и не внутри неё.
    Ну и пока что нет изменения баланса, но это ты уже допишешь.
    Ответ написан
    Комментировать
  • Как правильно создать и разделить разные функции под одним хендлером?

    Vindicar
    @Vindicar
    RTFM!
    Читаем документацию и учимся использовать встроенные средства бот-библиотеки.
    @bot.message_handler(func=lambda message: message.text == 'О нас')
    def blabla1(message):
        ...  # тут логика реакции на сообщение "О нас"
    
    @bot.message_handler(func=lambda message: message.text == 'Чем займёмся?')
    def blabla2(message):
        ...  # тут логика реакции на сообщение "Чем займёмся?"
    
    @bot.message_handler(func=lambda message: True)
    def whatever(message):
        ...  # тут логика реакции на все остальные сообщения. Эта функция должна идти строго последней.
    Ответ написан
    Комментировать
  • Есть ли аналог метода Range.AutoFill для работы с файлом в скрытом режиме?

    Vindicar
    @Vindicar
    RTFM!
    Нету такого метода, и вряд ли где-то будет, помимо другого табличного процессора. Там же очень замороченная логика - нужно догадаться, что за данные выделены, какая в них закономерность, как эту закономерность продолжить, в каком направлении её продолжить, и так далее.
    Если у тебя частный случай (например, нужна последовательность дат или последовательность чисел), и предсказуемое направление заполнения, то можно написать логику самому.
    Ответ написан
  • Как создать фоновую задачу в боте?

    Vindicar
    @Vindicar
    RTFM!
    Присоединюсь к советам выше.
    А вообще глянь мой пример, он должен работать для любой версии.
    Ответ написан
    Комментировать
  • Как вернуться из модуля обратно в main?

    Vindicar
    @Vindicar
    RTFM!
    Фигню творишь. Отношения между модулями должны быть строго односторонними - один модуль предоставляет сервис, другой его использует. В этом случае просто не будет необходимости в циклическом импорте.

    Если же у тебя более сложная ситуация, придётся выкручиваться. Например: main описывает бота, который используется модулем, который уже предоставляет сервис через этого бота. Тут ситуация усложняется телеботом, который не особенно пригоден для многомодульных ботов. Хотя есть приём, который можно сравнить с внедрением зависимостей.

    module1.py
    # бота передаём как параметр внутрь функции install_module
    # если у тебя будут другие глобальные ресурсы, скажем, соединение с СУБД, можно передавать их также
    def install_module(bot) -> None:  
        # да, мы описываем функцию прямо внутри другой функции. Так можно
        @bot.message_handler(commands=['some_command', ])
        def my_command(message):
            ...  # тут логика команды
    
        # и ещё одну...
        @bot.message_handler(commands=['other_command', ])
        def my_other_command(message):
            ...  # тут логика команды

    Тогда в main.py будет что-то вроде
    import telebot
    bot=telebot.TeleBot('TOKEN')
    # импортируем и активируем модуль
    import module1
    module1.install_module(bot)  # install_module() модуля должна вызываться строго однажды
    # модулей может быть несколько
    import module2
    module2.install_module(bot)
    # когда всё установлено, запускаем бота
    bot.infinity_polling()

    Идею можно развить таким образом: пусть твои модули лежат не рядом с main.py, а в подпапке modules. Тогда можно сделать что-то такое, чтобы автоматически подгрузить все модули из этой папки при старте бота.
    from pathlib import Path
    import sys
    import importlib
    
    import telebot
    
    bot=telebot.TeleBot('TOKEN')
    
    MAIN_DIR = Path(sys.argv[0]).parent.resolve()  # папка где лежит скрипт бота
    MODULES_DIR = MAIN_DIR / 'modules'  # лежащая рядом папка modules
    for item in MODULES_DIR.glob('*'):   # перебираем файлы и папки в папке modules
        # игнорируем папки и файлы, начинающиеся с _ или с .
        if item.name.startswith('_') or item.name.startswith('.'):
            continue
        # item - это имя пригодного для импорта модуля?
        if (item.isfile() and item.name.endswith('.py')) or (item.isdir() and (item / '__init__.py').isfile()):
            # да импортируем и активируем модуль
            module = importlib.import_module('modules.'+item.name)
            module.install_module(bot)
    
    # когда всё установлено, запускаем бота
    bot.infinity_polling()
    Ответ написан
    2 комментария
  • Почему в параметр функции идёт только последний индекс?

    Vindicar
    @Vindicar
    RTFM!
    Поздравляю, ты попался на лямбду.
    Лямбды сохраняют ссылки на переменные, а не их значения.
    lambda _: set_default_microphone(index) сохранит ссылку на index, а потому все лямбды будут видеть одно и то же значение index, которое было установлено последним.
    Это можно обойти, сохранив ссылку при объявлении лямбды. Самый простой способ - засунуть сохраняемое значение в значение по умолчанию для неиспользуемого параметра. Значения по умолчанию для параметров вычисляются один раз при объявлении функции, в т.ч. лямбды.
    Например, так:
    lambda _, *, ind=index: set_default_microphone(ind)

    Ну или даже так:
    lambda _, *, index=index: set_default_microphone(index)
    Ответ написан
    2 комментария
  • Как мне проигнорировать этот Подкаталог "old" и прочитать данные только из списка?

    Vindicar
    @Vindicar
    RTFM!
    from pathlib  import Path # входит в поставку питона, не сторонняя
    
    base_path = Path("data")  # путь до каталога с данными
    for item in base_path.glob('*'):
      if item.is_dir() and item.stem != 'old':
        # тут что-то делаем с путём item. Например:
        for kml_file in item.glob('*.kml'):
          print(kml_file.resolve())  # выводим полный путь к файлу
    Ответ написан
  • TypeError: Parameters to generic types must be types. Got Ellipsis.?

    Vindicar
    @Vindicar
    RTFM!
    Какая у тебя версия питона? Как минимум в 3.12 конструкция List[Dict[str, ...]] поддерживается. Может, и в более ранних тоже.
    Ответ написан
  • Решил попробовать в написание бота для TG, выходит ошибка RuntimeError?

    Vindicar
    @Vindicar
    RTFM!
    Без агрессии нельзя, это же интернет. Если тут не посылают, значит, что-то стряслось. =)

    Основой асинхронной программы является рабочий цикл (event loop). Он должен быть строго один. Я подозреваю, что у тебя создаётся более одного рабочего цикла, так как ты делаешь несколько вызовов get_event_loop() в придачу к asyncio.run().

    Я бы изменил код следующим образом: пусть класс базы данных принимает пул соединений как параметр конструктора. Аналогично, создай в основном файле глобальную переменную, которая будет хранить экземпляр этого класса. При создании присвой переменной None.

    А вот внутри main() уже делай всё остальное: создай экземпляр пула соединений, создать экземпляр класса БД (и закинь его в глобальную переменную), а потом запускай бота. Тогда у тебя все асинхронные операции будут происходить в рамках одного вызова main(), а значит, гарантированно в одном рабочем цикле.
    Ответ написан
    Комментировать
  • Методы для поиска объектов на изображениях?

    Vindicar
    @Vindicar
    RTFM!
    почитать подробно про методы

    Хотелось бы понять какой метод, для какой задачи больше походит

    Не, ну ты выбери что-то одно. Или ты въезжаешь в кишки одного метода, или ты ищешь инфу по верхам.

    Навскидку, ключевые вещи на которые нужно смотреть это трудоёмкость, инвариантность и поддержка множественных экземпляров. Первое определяет, насколько сложно подготовить детектор объектов этим методом. Второе определяет, сломается ли метод если искомый объект повернуть/увеличить/ярко осветить/и т.п. Третье определяет, сломается ли метод, если искомый объект присутсвует в нескольких экземплярах.

    Например, методы перебора с голосованием вроде алгоритма Хафа. Хорошо работает для геометрических примитивов, поддерживает несколько экземпляров. Но произвольные трансформации обрабатывает плохо, слишком много вариантов. Для задач вроде "найти кнопку на экране" подходит очень хорошо.

    Каскады Хаара. Требуют контрастных объектов, не справляются с поворотами, могут быть чувствительны к масштабы. Долго обучаются, но довольно быстро работают. Сейчас их редко применяют.

    Методы, основанные на локальных особенностях. Требуют "пёстрых" объектов с множеством заметных деталей (в идеале контрастных углов), и не справляются с деформируемыми объектами или очень разными ракурсами. Легко справляются с произвольными трансформациями, но ломаются на множественных экземплярах. Это придётся обходить, обрабатывая изображение по частям. Зато если объект простой (условно, обложка книги), им обычно хватает одного изображения.

    Свёрточные нейронки вроде семейства YOLO. Можно научить много на что, и скорость работы у них стабильная, но нужна большая размеченная база для обучения. Причём если в базе не было скажем, повёрнутых изображений, нейронка их не научится распознавать. Отчасти обучающую базу можно расширить джиттерингом, но готовить её всё равно придётся, причём речь идёт о сотнях и тысячах изображений.
    Ответ написан
    1 комментарий
  • Что делать, при печати, звук ошибки системы в PyCharm?

    Vindicar
    @Vindicar
    RTFM!
    Переключение по Alt-Shift? Это не только в pycharm такое.
    В винде нажатый и отпущенный Alt - это выход в главное меню окна. Приём это для большинства окон работает. А когда ты в главном меню, набор клавиш пытается выбрать подходящий пункт в главном меню. Если такого пункта нет - будет звук ошибки. И это еще хороший варинт, можешь выбрать фиг знает что.
    Я не до конца уверен при каких обстоятельствах Alt-Shift триггерит главное меню, но этого было достаточно, чтобы все свои компы перенастроить на Ctrl-Shift. Ну или точнее, использую AutoHotKey чтобы по нажатию CapsLock прожимался Ctrl-Shift, а это комбо уже переключате раскладку.
    Ответ написан
    Комментировать
  • Как найти паттерн на картинке с OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    Во-первых, оформи код, нечитаемо. Кнопка </> в помощь.
    Во-вторых, matchTemplate(), насколько я знаю, не-инвариантна к поворотам и масштабу. Иными словами, поворот или изменение размера целевого объекта сломают сопоставление.
    В-третьих, на показанном кадре более одного экземпляра целевого объекта. Так предполагается или нет? Если предполагается, сколько экземпляров ожидается? Потому что разница очень большая с точки зрения методики.

    Варианта тут три.
    1. пытаться обучать под задачу нейронку. А лучше дообучить существующую, скажем, YOLOv5. Но тебе потребуется минимум несколько сотен размеченных изображений объекта в разных комбинациях, плюс в 2-3 раза больше похожих изображений без целевого объекта. Готовить такую базу будет утомительно, да и само обучение требует понимания что ты делаешь.
    2. попробовать зафиксировать угол поворота или масштаб (т.е. допустить, что он всегда одинаков). Тогда другой параметр можно будет подбирать. Например, мы фиксируем масштаб и делаем 16 изображений объекта в разных поворотах, а потом поочерёдно ищем каждый вариант на кадре. Потом анализируем силу откликов - сколько их, насколько они сильные и т.д. Скорее всего, будет медленно
    3. взять за основу поиск по локальным особенностям. Он справляется с масштабом и поворотом, но не справляется с несколькими экземплярами объекта. Это можно забороть, если использовать скользящее окно. Иными словами, находим на кадре узнаваемые точки - локальные особенности (желательно достаточно много и достаточно плотно), используя алгоритмы вроде ORB или SIFT. Затем выбираем те из них, которые попадают в прямоугольную рамку-окно. Затем сверяем эти особенности с особенностями объекта, используя RANSAC или подобный метод. Если получилось хороше совпадение - значит, в этой рамке есть объект или значительная его часть, и мы можем оценить его позицию в кадре в целом. Повторяем процесс, сдвигая рамку, пока оно не "обойдёт" всё изображение. Тоже может быть небыстро, так как нам требуется неоднократный поиск по картинке.
    Ответ написан
    Комментировать