Задать вопрос
Ответы пользователя по тегу Python
  • Как правильно завершить процесс и все дочерние подпроцессы?

    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().
    Ответ написан
    Комментировать
  • Как правильно обработать # IndexError: string index out of range?

    Vindicar
    @Vindicar
    RTFM!
    Не перебирать в цикле строку до конца, а только до предпоследнего символа. Его обработать отдельно, если потребуется.
    А вообще, я бы переписал по другому. Просто храни в переменной последний увиденный символ.
    Тогда, пока ты идёшь по строке, у тебя есть два варианта:
    а) текущий символ совпал с последним увиденным. нарасти счётчик повторов на 1.
    б) текущий символ отличается. запиши счётчик в выходную строку, сбрось счётчик в 1, запомни текущий символ как последний.
    Ответ написан
    Комментировать
  • 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(), ни в доках она ни упоминается, ни в исходниках. Откуда ты взял, что она есть?
    Ответ написан
    Комментировать
  • Как превратить str(словарь) обратно в словарь?

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

    Vindicar
    @Vindicar
    RTFM!
    Сейчас код сначала получает текст, содержащий координаты точек из буфера обмена, потом разбирает и проверяет каждую строку и переспрашивает нужна ли она, а потом уже входит в цикл while True, где он их прокликивает и ожидает нажатия w или q.
    Нужно всю ту часть, где определяются координаты, а также сам код прокликивания внести внутрь ветки w.

    Как именно - спрашивай у того, кто написал код.
    Ответ написан
    Комментировать
  • Как сделать проверку роли у пользователя и выдачи второй роли, если первая роль есть?

    Vindicar
    @Vindicar
    RTFM!
    Программа не работает как именно? Отсутствие реакции? Сообщение об ошибке? Комп встаёт со стола и идёт искать Сару Коннор?
    Далее, ты проверил, on_guild_update() вообще вызывается? Хотя бы временный print() в начало вставь.
    Потому что если почитать документацию, там английским по белому написано:
    This requires Intents.guilds to be enabled.

    Какие интенты ты задаёшь боту?

    Ещё важнее: а причём тут вообще on_guild_update()? Это событие отрабатывает, когда изменяются настройки сервера, а из твоего описания следует, что тебя интересуют роли участников. За это отвечает on_member_update().

    Короче, нужно прояснить происходящее.
    Ответ написан
    Комментировать
  • Как понять когда ставить пробел в строках,а когда нет в Питоне?

    Vindicar
    @Vindicar
    RTFM!
    Дополню ответ выше: для print() поведение можно настроить параметром sep. Например:
    print(1, 2, 3)  # 1 2 3
    print(1, 2, 3, sep='')  # 123
    print(1, 2, 3, sep=', ')  # 1, 2, 3

    А еще есть параметр end:
    print(1, 2, 3)  # 1 2 3 с переводом на новую строку
    print(1, 2, 3, end='')  # 1 2 3 без перевода на новую строку
    print(1, 2, 3, end=':')  # 1 2 3: без перевода на новую строку

    Так что строку, выводимую print(*args), можно описать так:
    sep.join(str(arg) for arg in args) + end
    Ответ написан
    1 комментарий
  • Как в Python можно изменить запись в CSV?

    Vindicar
    @Vindicar
    RTFM!
    Нет, по-простому нельзя. Единственный простой подход (который показал выше Максим Припадчев) - загрузить целиком в память, там изменить, потом выгрузить назад. Для больших CSV файлов это ресурсоёмко.

    CSV вообще не предназначен для долговременного хранения данных - скорее, для импорта/экспорта.

    Ты мог бы попытаться использовать методы tell() и seek(), чтобы "запомнить" позицию удаляемой строки, а затем в цикле копировать всё что идёт после, "пододвинув" содержимое внутри файла, а потом уже дописать в конец изменённую строку. Но это всё равно долго.

    Лучше импортируй файл в базу SQLite, и работай в дальнейшем уже с ней.
    Ответ написан
    3 комментария
  • При запуске элементарного кода(правильного) на vkbottle выдает огромное количество ошибок. Что делать?

    Vindicar
    @Vindicar
    RTFM!
    aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host api.vk.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1002)')]

    У тебя или провайдер сильно хитропопый, или вирусня на компе. Самоподписанных сертификатов в цепочке сертификатов для любого нормального сайта быть не должно и точка, а для контакта тем более. Так что кто-то пытается перехватить соединение. Кто - без понятия. Проверь на заведомо чистой машине и работая через VPN, также проверь список установленных корневых сертификатов, нет ли там чего странного. Как - написано в гугле.
    Ответ написан
  • Как верно настроить вероятность в мини - игре?

    Vindicar
    @Vindicar
    RTFM!
    0. Главное: вопрос у тебя звучит "Как верно настроить вероятность". В коде ровно одна строчка с random, и ты не объясняешь что она делает. Собственно, и правила игры (т.е. желаемое поведение кода) ты не озвучил. Что такое "подкрутка"? Что тут посоветуешь...
    1. Если ты ловишь себя на том, что создаёшь переменные вида mine_3, mine_4, mine_5, а дальше делаешь x = eval(f"mine_{mines_kolv}[{now_state}]") тебе нужна индексируемая коллекция! Список или кортеж. Тем более что списки ты уже используешь, значит, знаешь, что это такое. Неужели "список из списков" - это такая сложная концепция?
    2. У тебя в самом первом SQL-запросе подстановка параметров выполняется корректно, а дальше идёт ересь с использованием %-форматирования. Не надо так.
    3. У тебя куча таблиц, из которых ты вытаскиваешь по одному значению. Если эти значения всегда требуются вместе, почему не объединить их в одну таблицу?

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

    Vindicar
    @Vindicar
    RTFM!
    AudioSegment.converter = f"{os.getcwd()}\\ffmpeg.exe"

    Ты уверен, что файл лежит в текущем каталоге? Это не то же самое, что каталог программы.
    Если тебе нужен каталог программы, лучше его и взять:
    from pathlib import Path
    import sys 
    
    SCRIPT_DIR = Path(sys.argv[0]).parent.resolve()
    FFMPEG = SCRIPT_DIR / 'ffmpeg.exe'  # чтобы не париться с разделителем каталогов (/ или \)
    Ответ написан
    Комментировать
  • Как запихнуть в threading.Timer() async-функцию?

    Vindicar
    @Vindicar
    RTFM!
    Если ты хранишь ссылки в БД, то я бы просто сделал отдельную задачу через create_task(), которая с некоторой периодичностью выбирает из БД истекшие ссылки (запрос будет вполне тривиален), рассылает по ним оповещения, а потом удаляет из БД. При таком сценарии таймаут на ссылку переживёт перезапуск бота.
    В принципе можно и без БД, лишь бы в твоём хранилище ссылок хранились сведения о том, когда ссылка должна истечь.
    Ответ написан
    Комментировать
  • Как получить доступ к свойству объекта JSON не зная его название?

    Vindicar
    @Vindicar
    RTFM!
    JSON-объекты загружаются в простой питоновский словарь (а массивы - в список).
    Так что окей, гугл, перебор элементов словаря python.

    В твоём случае что-то вроде
    pages = info["query"]["pages"]
    for page_id, page_data in pages.items():
        ...   # что-то делаешь с page_id и page_data


    Если ты уверен, что у тебя всегда ровно один элемент в словаре, и его ключ тебя не интересует, то можно и так:
    pages = info["query"]["pages"]
    if pages:  # есть что-то в словаре?
        page_data = list(pages.values())[0]
        ...   # работаешь с page_data
    Ответ написан
    1 комментарий
  • Как запустить скрипт используя subprocess и venv из которого запущен главный скрипт?

    Vindicar
    @Vindicar
    RTFM!
    Найди бинарник python, который лежит в этом venv, и укажи его полный путь вместо просто python.
    Но так как ты дожидаешься завевршения скрипта, может иметь смысл такой хак:
    # my_script.py
    import sys
    
    def main(args: list[str]):
        """Тело скрипта здесь..."""
    
    if __name__ == '__main__':
        # скрипт запущен независимо
        main(sys.argv[1:])

    А в главном скрипте будет просто
    import my_script
    
    my_script.main(['--work-dir', work_dir, '--result-dir', result_dir])


    В этом случае тебе не придётся сильно переделывать my_script. Но зато теряешь в удобстве вызова кода, например, если нужно получить значение из этого скрипта.
    Чем больше ты вынесешь из main() в отдельные подпрограммы - тем больше контроля будет у главного скрипта, но и тем больше работы.
    Ответ написан
    Комментировать