• Как правильно завершить процесс и все дочерние подпроцессы?

    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, запомни текущий символ как последний.
    Ответ написан
    Комментировать
  • Почему бот отправляет "0"?

    Vindicar
    @Vindicar
    RTFM!
    Документацию читать надо.
    os.system() возвращает числовой код завершения запущенного процесса (0 - завершилась успешно). Стандартный вывод этого процесса молча отправляется в стандартный вывод твоей консоли.
    Если тебе нужен перехватить стандартный вывод, используй средства модуля subprocess.
    А если тебе нужно мониторить изменения файла, используй пакет watchdog.
    Ответ написан
    4 комментария
  • Discord бот не видит файл "prefix.txt", как решить?

    Vindicar
    @Vindicar
    RTFM!
    Ну я бы сказал, зачем это вообще?
    Во-первых, дискорд активно подталкивает ботов на использование слэш-команд, которым префикс не нужен.
    Во-вторых, дискорд.пи и его клоны типа nextcord имеют параметр бота command_prefix. Если таки осилить открыть документацию, то найдём там такое:
    The command prefix is what the message content must contain initially to have a command invoked. This prefix could either be a string to indicate what the prefix should be, or a callable that takes in the bot as its first parameter and nextcord.Message as its second parameter and returns the prefix.


    Т.е. вместо тупо строки префикса можно передать функцию вида def prefix_func(bot, message) -> str:, которая будет вызываться для каждого сообщения, и возвращать желаемую строку префикса. Это не только позволяет менять префикс динамически, не трогая бота (бот как дёргал функцию, так и будет дёргать), но и позволяет делать вещи типа "свой префикс у разных серверов".

    И никаких велосипедов изобретать не потребуется. Всё уже придумано.
    Ответ написан
    1 комментарий
  • Как зациклить это действие?

    Vindicar
    @Vindicar
    RTFM!
    Цикл while?
    Не, серьёзно. Это основы языка. Открой учебник и читай.
    Ответ написан
    Комментировать
  • Что за ошибка в python?

    Vindicar
    @Vindicar
    RTFM!
    Поясню ответ Алан Гибизов: Обратный слэш (\) в строковых литералах Питона (как и во многих языках) имеет специальное значение, зависящее от следующего символа. Например, \n означает символ перевода строки, \t - символ табуляции, и т.д. Последовательность \u позволяет задать символ юникода по его коду, например, символ \u00A7 это значок параграфа (§). Но это также разделитель каталогов в пути на платформе Windows. А у тебя в пути есть последовательность "C:\Users\777\Desktop\Новая папка\67.png".
    Избежать этого конфликта можно одним из трёх способов:
    * использовать последовательность \\ - она означает просто символ \ без специального поведения.
    * использовать "сырой" строковой литерал - my_path = r'C:\Users\'. В таких литералах символ \ не имеет специального поведения, это просто символ.
    * Записать путь, используя прямой слэш /. Винда это позволяет.
    Ответ написан
    Комментировать
  • Есть код на питоне как можно ускорить его мультипроцессность не работает?

    Vindicar
    @Vindicar
    RTFM!
    p = multiprocessing.Process(target=gen,args=(lst,))
    p.start()

    Ты запускаешь ровно один процесс, а потом стоишь и ждёшь (p.join()), когда он завершится. Это мало чем отличается от просто вызова gen() в твоём коде, безо всякого мультипроцессинга.
    Кроме того, у тебя функция gen() делает всю работу, а должна обрабатывать только один элемент. Ты думаешь Питон волшебным образом поймёт, что вот именно этот цикл надо распараллелить?

    Используй пул процессов multiprocessing.Pool, он принимает функцию и последовательность входных значений, а потом скармливает эти значения по одному в копии указанной функции в нескольких процессах, и собирает из них ответы.

    Пример есть в документации, если ты туда заглядывал. В примере показано несколько вариантов использования пула процессов.
    Я бы на твоём месте использовал или imap_unordered(), или imap(). Разница в том, что первый может не сохранять порядок - т.е. результаты тебе будут приходить не в том же порядке, в каком приходили данные во входной последовательности. Второй его сохраняет, но работает чуть медленнее (он ждёт, пока правильный порядок не получится).
    Ответ написан
    6 комментариев
  • Как превратить str в словарь (2 часть)?

    Vindicar
    @Vindicar
    RTFM!
    Сам словарь полученный от телеграмм мне нужно его в нужном моменте сохранять в бд, а позже вытаскивать обратно превращая назад в dict, но все идет по наклонной

    Ну т.е. как и предсказывали, проблема в более раннем коде.
    Когда сохраняешь в БД, делай не str(mydict), а json.dumps(mydict). Тогда можно будет делать json.loads() при загрузке.

    Только словарь надо будет почистить от постороннего, а ещё лучше - сначала сделать свой словарь ,в который сохранять ТОЛЬКО то, что тебе надо. Например, ты не заметил, что у тебя в словаре есть
    'entities': [<telebot.types.MessageEntity object at 0x7770137fd0>]

    Сюрприз-сюрприз, объект
    <telebot.types.MessageEntity object at 0x7770137fd0>
    явно сериализации не поддаётся, и ни сохранить, ни восстановить его не выйдет. Или убирать ключ entities, если он тебе не нужен, или разбираться, что это за объект и сериализовывать/восстанавливать его вручную.
    Ответ написан
    3 комментария
  • Не ищет картинку. Python?

    Vindicar
    @Vindicar
    RTFM!
    Ну правильно тебе питон говорит. У pyautogui нет функции loadImage(), ни в доках она ни упоминается, ни в исходниках. Откуда ты взял, что она есть?
    Ответ написан
    Комментировать
  • Не запускается бот в дискорд, что делать?

    Vindicar
    @Vindicar
    RTFM!
    Всё, что начиная с
    @bot.event 
    async def on_ready():

    нужно подвинуть влево (уменьшить отступ). В питоне отступы значимы!
    Советую ненадолго отложить бота и поучить язык на более простых примерах, во избежание подобных ошибок.
    Ответ написан
    Комментировать
  • Есть ли для Python простые в использовании ORM с поддержкой asyncio и type hints?

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

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

    Vindicar
    @Vindicar
    RTFM!
    Создай многострочное поле ввода, у запущенного процесса периодически опрашивай стандартный вывод. Если удалось что-то прочитать - добавляй прочитанное в поле ввода.
    Ответ написан
    Комментировать
  • Как превратить str(словарь) обратно в словарь?

    Vindicar
    @Vindicar
    RTFM!
    Лучше задайся вопросом, почему вообще у тебя str() от словаря?
    Веб-сервисы возвращают текст в формате json, который нужно декодировать через json.load() / json.loads().
    После декодирования ты получаешь собственно словарь, с которым можно работать.
    Короче, у тебя что-то напутано выше по коду, в том участке, который ты не показываешь. Покажи весь код.
    Ответ написан
    Комментировать
  • Как перебрать 5 или более списков в одном цикле?

    Vindicar
    @Vindicar
    RTFM!
    А как перебирать-то, чудо?
    Параллельно?

    list1 = list('abcdef')
    list2 = list('klmnop')
    list3 = list('uvwxyz')
    
    for item1, item2, item2 in zip(list1, list2, list3):
        print(item1, item2, item2)


    Последовательно?

    import itertools
    
    list1 = list('abcdef')
    list2 = list('klmnop')
    list3 = list('uvwxyz')
    
    for item in itertools.chain(list1, list2, list3):
        print(item)


    Во всех сочетаниях?

    import itertools
    
    list1 = list('abcdef')
    list2 = list('klmnop')
    list3 = list('uvwxyz')
    
    for item1, item2, item3 in itertools.product(list1, list2, list3):
        print(item1, item2, item3)

    Ответ написан
    Комментировать
  • Как я могу запустить скрипт в Pycharm, используя CMD?

    Vindicar
    @Vindicar
    RTFM!
    В общем, по итогам обсуждения:
    Я бы разобрался, как работает venv. Pycharm всё-таки очень жоркая штука, не надо его использовать просто как среду выполнения. Вообще, ЕМНИП, достаточно вызвать python.exe, который лежит внутри окружения проекта. Что-то типа
    cd C:\my_project\
    .venv\bin\python3.exe main.py

    Если этого мало - разбирайся со скриптом activate.
    Шрифт и цвет терминала тоже поддаётся настройке, если что.

    Но если прям невтерпёж удалить гланды через задницу
    Найди способ послать в PyCharm сочетание Ctrl-Shift-F10, оно запускает текущий файл. Это можно сделать через тот же питон (модули типа pywinauto или pyautogui), или используя стороннее ПО типа AutoHotkey.
    Ответ написан
    1 комментарий
  • Как создать ярлык в python?

    Vindicar
    @Vindicar
    RTFM!
    Лучше через реестр добавляй, в
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    . Эта ветка должна быть открыта на доступ пользователю. Как работать с реестром из-под питона - гугли.
    Ответ написан
  • Возможно ли раздать Wi-Fi через спутник?

    Vindicar
    @Vindicar
    RTFM!
    Передавать-то на Wi-Fi частоте ты может и сможешь... а вот как телефон спутнику отвечать будет? Антенну и батарейки придётся в рюкзаке носить. =)
    Ответ написан
    1 комментарий