• Как рисовать блок схемы для функциональных программ?

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

    Vindicar
    @Vindicar
    RTFM!
    Зависит от текущего уровня знаний.
    1. Убедись, что знаешь хотя бы основы языка Python и умеешь искать недостающую информацию.
    2. Освой хотя бы фреймворк для работы с телегой, типа pyTelegramBotAPI или Aiogram.
    Напиши пару простых ботов, для начала - эхобот.
    3. Продумай сценарий взаимодействия пользователя с ботом. Какие инструменты потребуются? Будет ли взаимодействие на уровне "команда - ответ", или же понадобятся сценарии (FSM)?
    4. Посмотри, есть ли в выбранном фрейсмворке нужные инструменты, попробуй их освоить на примере простых ботов.
    5. Приступай к своему боту.
    Ответ написан
    Комментировать
  • Как вызвать одну функцию из другой в discord боте?

    Vindicar
    @Vindicar
    RTFM!
    Советую не пытаться удалять гланды через противоположный конец тела. А именно:
    Вместо того, чтобы пытаться вызвать обработчик команды, и биться об стенку, пытаясь имитировать всё необходимое окружение, следует просто вынести непосредственно операцию поиска в ОТДЕЛЬНУЮ функцию.
    Собственно, в твоём случае было бы норм и просто вызвать
    search_results = googlesearch.search(query, num_results=3)
    внутри ask(), и обработать полученные результаты - невелико повторение. Я бы сделал именно так.

    Если прям очень хочется сделать общий код для двух команд, вынеси в отдельную функцию и вывод:
    # Messageable - это что-то, чему можно послать текстовое сообщение. Это может быть канал, пользователь, контекст команды...
    async def search_and_reply(query: str, ctx: discord.abc.Messageable) -> None:
        try:
            search_results = googlesearch.search(query, num_results=3) 
            if search_results:
                await ctx.send("Результаты поиска в Google:")
                for result in search_results:
                    await ctx.send(result)
            else:
                await ctx.send("Ничего не найдено.")
        except Exception as e:
            await ctx.send(f"Произошла ошибка при выполнении поиска: {str(e)}")

    И тогда у тебя будет всё проще: search() будет состоять из одного вызова await search_and_reply(query, ctx), но будет брать на себя регистрацию как обработчика команды, проверку ролей и кулдаунов, и прочую мишуру, которой не место внутри search_and_reply(). Тогда ask() может просто сделать аналогичный вызов await search_and_reply(query, channel) в нужный момент, не беспокоясь о специфике дискорд-обработчика, так как search_and_reply() таковым не является.
    Ответ написан
    Комментировать
  • WebSocket connection to 'wss://localhost:12345/' failed в чем ошибка?

    Vindicar
    @Vindicar
    RTFM!
    Коннектится надо не на localhost, а на тот домен, для которого выпущен твой сертификат. Иначе обломаешься на уровне TLS-соединения (сертификат не для того домена).
    Ответ написан
  • Я пишу музыкального бота для Discorda, но выводит ошибки. Не могу понять в чем именно проблема?

    Vindicar
    @Vindicar
    RTFM!
    Ну тебе же прямым английским текстом написано: ты обращаешься к объекту, описывающему сервер(гильду), и пытаешься у него добыть свойство voice, а такого свойства нет.
    server.voice.channels - получить у объекта сервер свойство voice, а у объекта в этом свойстве - свойство channels.
    И в документации свойства voice у объектов класса Guild тоже нет. Зато есть voice_channels.
    Ответ написан
    Комментировать
  • Как из цикла for получить последовательный ответ в одну строку?

    Vindicar
    @Vindicar
    RTFM!
    Советую поучить стандартную библиотеку языка, а потом уже браться за такие вещи.
    У тебя в коде уже есть пример, как список строк превратить в одну строку, соединив их разделителем.
    spisok = "".join(llavw)
    В чём проблема адаптировать этот же метод к твоей задаче? Сформируй список из отдельных строк, потом объедини их. Единственно, стоит убедиться, что ты подаёшь на вход именно список строк, а не каких-то других объектов.
    Ответ написан
    8 комментариев
  • Как исправить ошибку tkinter Python?

    Vindicar
    @Vindicar
    RTFM!
    Значит, ты в какой-то момент делаешь в глобальной области видимости присваивание вида execute = tkinter.Button(...)
    Ответ написан
    1 комментарий
  • Как распознать тип движения с помощью opencv?

    Vindicar
    @Vindicar
    RTFM!
    Можешь познакомиться с этой лекцией, там есть интересные идеи.
    Ответ написан
    Комментировать
  • Ког не загрузился, как решить?

    Vindicar
    @Vindicar
    RTFM!
    Читаем документацию на класс disnake.Client, видим, что никакого атрибута cluster там нет.
    Почему ког обращается к этому атрибуту - спрашивай того, кто этот код написал.
    Ответ написан
    Комментировать
  • Ошибка при скачивании pdf-файлов, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    Легко проверить. Ты делаешь:
    url = "https://file.11klasov.net/index.php?do=download&id=16985" # замените на URL файла, который вы хотите скачать
    response = requests.get(url)

    Затем посмотри атрибут response.history, и ты увидишь там два ответа: [<Response [302]>, <Response [301]>]. Все коды 3XX - это перенаправления, т.е. сайт тебя перенаправляет на другую страницу, вместо того, чтобы отдать контент.
    Итог этих перенаправлений можно узнать из response.url, который будет равен
    'https://file.11klasov.net/13938-russkij-jazyk-7-klass-razumovskaja-mm-lvova-si-kapinos-vi-i-dr.html'

    Т.е. сайт задетектил бота, и отправил тебя на страницу учебника. Так обычно борятся с хотлинкингом, когда кто-то ставит прямую ссылку на файл на твоём сайте.
    Также можно проверить response.headers['content-type']. Он будет 'text/html; charset=utf-8', т.е. это HTML страница а не PDF файл. Разумеется, если ты HTML страницу запишешь в файл с расширением .pdf, она от этого не станет валидным PDF.

    Обычно проверяются две вещи: User-Agent и Referer. Первый описывает браузер пользователя, второй - с какой страницы был переход по этой ссылке. Но для данного сайта, похоже, достаточно добавить только Referer вот так:
    response2 = requests.get(url, headers={
        'referer': response.url,  # ну или 'https://file.11klasov.net/13938-russkij-jazyk-7-klass-razumovskaja-mm-lvova-si-kapinos-vi-i-dr.html'
    })

    То получишь желаемое - response2.history будет пустой, а response2.headers['content-type'] будет равен 'application/pdf'.

    С учётом этого можешь поправить свой код, чтобы он детектил редирект и делал второй запрос с заголовком Referer.
    Ответ написан
    Комментировать
  • Как искать по своим вопросам или ответам?

    Vindicar
    @Vindicar
    RTFM!
    Я обычно использую запрос вида
    inurl:qna.habr.com/q/ "@Username" Ключевые слова для поиска

    К сожалению, по URL qna.habr.com/user/Username/answers гугл не ищет, хотя в robots.txt он не запрещён.
    Ответ написан
    Комментировать
  • Как убрать символы [] () '', при выводе информации из списка?

    Vindicar
    @Vindicar
    RTFM!
    Перебирай элементы циклом for и выводи по одному, или используй str.join().
    print(', '.join(a))
    Ответ написан
  • Что делать при данной ошибке?

    Vindicar
    @Vindicar
    RTFM!
    Вместо
    member_full = bot.get_user(id=id)
    banned_users = await ctx.guild.bans()
    for ban in banned_users: ...

    Нужно
    member_full = bot.get_user(id=id)
    async for ban in ctx.guild.bans(): ...

    async for x in y - это не то же самое, что и for x in await y. Асинхронный генератор (первый случай) каждый элемент запрашивает асинхронно, а во втором случае - асинхронно запрашивается вся коллекция, которая потом синхронно итерируется. Разные подходы, разные методы, так что объект вполне может поддерживать только один из них.
    Ответ написан
    Комментировать
  • Как найти слагаемые числА, используя только слагаемые из списка?

    Vindicar
    @Vindicar
    RTFM!
    Я бы решал задачу рекурсией.
    У тебя есть два варианта.
    а) Раскладываемое число есть в списке. Тогда это число и будет единственным слагаемым.
    б) Раскладываемого числа нет в списке. Тогда последовательно перебирай числа из списка, меньшие раскладываемого числа - возможные слагаемые.

    Если нашел такое число, то:
    1. Вычитаешь его из раскладываемого числа
    2. Убираешь из списка его и все более ранние числа.
    3. Пробуешь решить задачу для нового раскладываемого числа и нового списка чисел.
    4. Если решение нашлось, возвращаешь результат выше, добавив к нему то возможное слагаемое, которое ты обрабатывал.

    Т.е., иными словами, у тебя будет функция вида:
    def sum_split(summa: int, candidates: list[int]) -> list[int]:

    Если summa присутствует в candidates, то возвращаешь [summa].
    Иначе перебираешь список candidates, и для каждого числа candidates[i] делаешь рекурсивный вызов
    answer = sum_split(summa - candidates[i], candidates[i+1:])
    .
    Если список answer не пуст, добавляешь к этому списку candidates[i] и возвращаешь его сам.
    А если перебрал весь список и ничего не подошло, возвращаешь пустой список.

    Дальше сам.
    Ответ написан
    3 комментария
  • Ошибка: cv2.error: OpenCV(4.8.0) :-1: error: (-5:Bad argument) in function 'cvtColor', как исправить?

    Vindicar
    @Vindicar
    RTFM!
    Почитать документацию на cvtColor() и осознать, что она принимает на вход объект изображения, а не VideoCapture(), который ты ей передаёшь. Так что тебе придётся преобразовывать в нужную цветовую систему каждый кадр отдельно.

    А еще почитать доки на VideoCapture(), в частности, про метод read(). Пример кода там есть.
    Ответ написан
    Комментировать
  • Как правильно завершить процесс и все дочерние подпроцессы?

    Vindicar
    @Vindicar
    RTFM!
    В-нулевых, не прячь импорты, не всегда понятно что откуда берётся.
    Во-первых, зачем тебе два уровня вложенности в процессах? Сначала делаешь дочерний процесс через multiprocessing.Process, а потом в нём запускаешь еще один процесс через Popen. Смысл? Собственно, результат предсказуем - ты жестко прибиваешь (kill()) первый дочерний процесс, и он не успевает ничего сделать со вторым.
    Во-вторых, Popen уже имеет полезные методы типа terminate(). Но тут есть тонкость - под линуксом этот метод посылает сигнал SIGTERM, на который процесс может отреагировать и спокойно завершить свою работу. Под виндой используется функция WinAPI TerminateProcess(), которая жёстко прибивает процесс, не давая ему шанса завершить работу. Будет практичнее использовать метод signal() в сочетании с константой signal.CTRL_C_EVENT - это будет эквивалентом нажатия Ctrl-C (или Ctrl-Break) в консоли дочернего процесса. Большинство процессов реагируют на это завершением работы. Но под виндой надо будет указать дополнительный параметр для Popen(), чтобы это сработало.

    Так что я бы попробовал что-то в таком духе:
    import signal
    import subprocess
    import sys
    
    args = [
        "ffmpeg", 
        "-i", f"rtsp://{camera_login}:{camera_pass}@{camera_host}:554/Streaming/channels/1/", 
        "-err_detect", "ignore_err", 
        "-reorder_queue_size", "0", 
        "-map", "0:v", "-c:v", "copy", 
        "-f", "rtsp", 
        "-rtsp_transport", "tcp", f"rtsp://{rtsp_server}:8554/live.stream"
    ]
    params = {'cwd': '.'}
    if sys.platform == 'win32':  # винда у нас особенная...
        params['creationflags'] = (
            # subprocess.DETACHED_PROCESS |  # если хочешь, чтобы ffmpeg запускался тихо и не спамил в твой stdout
            # subprocess.CREATE_NEW_CONSOLE |  # если хочешь, чтобы открывалась новая консоль для ffmpeg
            subprocess.CREATE_NEW_PROCESS_GROUP  # по докам, это требуется для нормальной работы ctrl-c
        )
    my_subprocess = Popen(args, **params)
    try:
        pass # тут работаешь с процессом
    finally:
        my_subprocess.signal(signal.CTRL_C_EVENT)  # сигналим процессу о завершении
        try:
            my_subprocess.wait(timeout=5.0)  # ждём завершения
        except subprocess.TimeoutExpired:  # процесс "задумался"
            my_subprocess.kill()  # тогда прибиваем
    Ответ написан
    Комментировать
  • Как можно оптимизировать silero tts?

    Vindicar
    @Vindicar
    RTFM!
    Я не вижу, что за время ты измеряешь, и что пытаешься оптимизировать.
    Всё, что выше вызова model.apply_tts(), по-хорошему должно выполняться только один раз при запуске программы, а не для каждой генерируемой фразы.
    Последовательность sd.play()-sd.stop() вообще не поддаётся оптимизации, это воспроизведения звука.
    Так что замерять стоит только model.apply_tts().
    Ответ написан
    Комментировать
  • Зачем нужны class в Python?

    Vindicar
    @Vindicar
    RTFM!
    Если у тебя функция не зависит ни от чего другого, и живет сама по себе - она и должна быть свободно-стоящей функцией.

    А классы нужны для случаев, когда у тебя есть набор данных (состояние) и поведение, относящиеся к одной сущности.
    Наглядный пример: файл. У него есть состояние - скрытые данные, например, дескриптор файла, правила чтения/записи, и т.п. вещи. И у него есть поведение - операции чтения, операции записи, закрытия и т.п.
    Если эти операции оформить как функции, то им придётся передавать всё состояние файла явно, через параметры. А значит, программисту, который будет работать с файлом, придётся быть в курсе, как файл устроен внутри. Ему будет сложнее писать программу.
    Если же мы обернём файл в объект, ситуация меняется. Теперь это состояние оказывается скрыто внутри объекта. Программисту достаточно иметь в своём распоряжении объект (экземпляр класса), и знать его "видимые снаружи" операции и свойства, а от внутреннего устройства он может абстрагироваться и вообще о нём не думать. Это здорово упрощает жизнь.
    Ответ написан
  • Как правильно обработать # IndexError: string index out of range?

    Vindicar
    @Vindicar
    RTFM!
    Не перебирать в цикле строку до конца, а только до предпоследнего символа. Его обработать отдельно, если потребуется.
    А вообще, я бы переписал по другому. Просто храни в переменной последний увиденный символ.
    Тогда, пока ты идёшь по строке, у тебя есть два варианта:
    а) текущий символ совпал с последним увиденным. нарасти счётчик повторов на 1.
    б) текущий символ отличается. запиши счётчик в выходную строку, сбрось счётчик в 1, запомни текущий символ как последний.
    Ответ написан
    Комментировать