Ответы пользователя по тегу Python
  • Как сделать закрытие окна по названию Python на Linux и на Windows?

    Vindicar
    @Vindicar
    RTFM!
    Я тебе больше скажу, под линуксом есть несколько оконных менеджеров - Gnome, KDE, Xfce из числа популярных.
    Хотя многие менеджеры базируются на X-Server, так что любое решение, использующее базовые возможности X-Server, будет более-менее универсальным. Например, можешь попробовать команду wmctrl.
    Если я верно понял справку по ссылке выше, то
    wmctrl -c 'Имя моего окна' должно закрыть первое окно, в заголовке которого встречается подстрока "имя моего окна" без учёта регистра.
    wmctrl -F -c 'Имя моего окна' должно закрыть первое окно, заголовок которого в точности равен "Имя моего окна".
    Это сработает для Xfce и KDE X11, но не для KDE Wayland, например. Насчёт Gnome не уверен.

    А вообще стоит задаться таким вопросом: тебе нужно именно закрыть отдельное окно, или завершить процесс, который это окно породил? Потому что если второе, то под линуксом это делается намного проще и универсальнее.
    Ответ написан
    Комментировать
  • Как при закрытии главного окна закрывались все остальные окна?

    Vindicar
    @Vindicar
    RTFM!
    class MainWindow(tk.Tk):
        """Главное окно приложения."""
        def __init__(self):
            """Конструктор вызывается при создании окна"""
            super().__init__()
            self.title('Моё окно')
            self.protocol('WM_DELETE_WINDOW', self.__done)  # прописываем реакцию на закрытие окна
            ...  # тут создаёшь элементы управления и проводишь прочую инициализацию
            # в том числе создаёшь и запоминаешь вспомогательные окна
    
        def __done(self):
            """Вызовется при попытке закрытия окна"""
            ...  # тут делаешь что тебе нужно при закрытии
            # например, закрываешь вспомогательные окна
            self.destroy()  # если не сделать этот вызов, окно на самом деле не закроется - иногда это нужно
    
    if __name__ == '__main__':
        root = MainWindow()
        root.mainloop()
    Ответ написан
    2 комментария
  • Как принудительно завершить дополнительный поток (thread)?

    Vindicar
    @Vindicar
    RTFM!
    Просто прибить поток технически можно, но на практике чревато - нет способа контроля за тем, когда поток прибьётся, так что если это произойдёт в неподходящий момент, внутренняя машинерия питона может сломаться.

    Лучше проектируй свой счётчик времени, что тут скажешь. Хотя я бы лучше само воспроизведение звука вынес бы в отдельный поток, а главный поток пускай занимается трекингом.

    Пример, как можно сделать поток с ожиданием И быстрым прибитием.
    def long_worker_thread(event: threading.Event):
        ...  # тут начальная подготовка. имей ввиду, что цикл начнётся с ожидания
        while not event.wait(1.0):  # ждём пока пройдёт заданное время - или пока event не будет взведено
            ...  # тут работу работаем - но не слишком долго, чтобы проверки event.wait() делались регулярно!
        ...  # завершение. Произойдёт, если был сделан break, или если event было взведено
    
    stop_worker = threading.Event()
    thread = threading.Thread(target=long_worker_thread, args=(stop_worker,))
    thread.start()
    ...  # что-то делаем пока поток крутится
    stop_worker.set()  # ожидание в потоке прервётся немедленно, не дожидаясь конца интервала
    thread.join()  # поэтому можно спокойно дождаться, пока поток не закончит работу - это будет быстро
    Ответ написан
  • Как установить таймаут и лимит попыток подключений asyncio?

    Vindicar
    @Vindicar
    RTFM!
    И то и другое делается руками.
    Для таймаута, заверни вызов open_connection() в вызов asyncio.wait_for().
    Для нескольких попыток, for _ in range(попыток).

    В итоге получим что-то вроде:
    for _ in range(attempts):
        try:
            reader, writer = await asyncio.wait_for(
                asyncio.open_connection(server, port),
                timeout
            )
        except (asyncio.TimeoutError, Exception):
            ...  # реагируем на ошибку соединения, пишем в лог или ещё что
        else:
            break  # соединение принято
    else:  # относится к for, выполнится если не было break
        ...  # реагируем на исчерпание попыток
        # потом делаем return или throw
    # если управление дошло досюда, соединение установлено
    ...  # работаем
    Ответ написан
    Комментировать
  • Как оптимизировать код на Python во времени?

    Vindicar
    @Vindicar
    RTFM!
    Тебе незачем генерировать все возможные перестановки, чтобы найти нужную.
    Прочитай внимательно приведённый пример: на каждое изменение первой цифры приходится 3 цифры всего - 1 задействованная = 2 изменения второй цифры. Поэтому, чтобы добраться до первой цифры, равной 3, нужно будет пропустить минимум 4 перестановки: две для смены 1 на 2 и две для смены 2 на 3, так как каждое изменение второй цифры означает одну перестановку. А значит, искомый номер будет не менее 5. Если бы цифр было больше, то каждое изменение второй цифры означало бы более 1 перестановки.
    Аналогичные рассуждения выполняешь для последующих цифр, с поправкой на то, что у тебя будет больше задействованных цифр. Таким образом, наращиваешь искомый номер, пока не достигнешь заданной перестановки.
    Ответ написан
    9 комментариев
  • Как работают рекурсии?

    Vindicar
    @Vindicar
    RTFM!
    Raddzor788,
    Где хранятся все эти значение 1,2,3,4, ведь у моего 'x' нету же звездочки(*х), чтобы собрать столько аргументов.

    Твой x - это несколько разных x. Потому что есть такая вещь как области видимости. Обычно есть область видимости функции (локальная) и глобальная область видимости скрипта. Если функция не видит нужного имени в локальной области - она ищет в глобальной. Если не видит и там - ищет в __builtins__.
    0. По умолчанию есть глобальная область видимости скрипта.
    1. При вызове func(1) создаётся локальная область видимости (скажем, А), в ней создаётся имя x, указывающее на 1.
    2. Отработало условие 1 < 4.
    3. Вызывается func(2). При этом создаётся НОВАЯ локальная область видимости Б (потому что новый вызов функции), в ней создаётся имя x, указывающее на 2.
    4. Отрабатывает условие 2 < 4.
    5. Вызывается func(3). При этом создаётся локальная область видимости В, в ней создаётся имя x, указывающее на 3.
    6. Отрабатывает условие 3 < 4.
    7. Вызывается func(4). При этом создаётся локальная область видимости Г, в ней создаётся имя x, указывающее на 4.
    8. Условие 4 < 4 не отрабатывает. Происходит вызов print(x) - имя x находится в текущей локальной области Г, выводится ассоциированное с ним значение 4. Отрабатывает print(4), происходит возврат из функции, область видимости Г уничтожается.
    9. Происходит вызов print(x) в предыдущем "слое" рекурсии. Текущая локальная область видимости В - в ней имя x связано со значением 3. Отрабатывает print(3), происходит возврат из функции, область видимости В уничтожается.
    10. Происходит вызов print(x) в предыдущем "слое" рекурсии. Текущая локальная область видимости Б - в ней имя x связано со значением 2. Отрабатывает print(2), происходит возврат из функции, область видимости Б уничтожается.
    11. Происходит вызов print(x) в предыдущем "слое" рекурсии. Текущая локальная область видимости А - в ней имя x связано со значением 1. Отрабатывает print(1), происходит возврат из функции, область видимости А уничтожается.
    12. Мы вышли из всех слоёв рекурсии. Мы находимся в теле скрипта и работаем только с глобальной областью видимости.
    Ответ написан
    Комментировать
  • Как увеличить паузу между отправкой запроса и получением результата?

    Vindicar
    @Vindicar
    RTFM!
    Время на формирования ответа сервера определяется самим сервером, ты на него повлиять не можешь.
    Если сервер тебе отправляет 10 результатов поиска вместо 30 - значит, либо ты сам запросил только 10, либо в базе есть только 10 подходящих элементов, либо действует какое-нибудь ограничение (для бесплатных пользователей. например?).

    В любом случае, без кода говорить не о чем.
    Ответ написан
  • Почему asyncio.current_task() не передается в функцию?

    Vindicar
    @Vindicar
    RTFM!
    Цитата из документации:
    Return the currently running Task instance, or None if no task is running.

    Как я это понимаю, если ты запланировал выполнение функции как задачи через asyncio.create_task(), то эта функция, и все, вызываемые в ней, смогут получить объект задачи, вызвав asyncio.current_task().
    Если же управление в текущую функции было передано без использования задач на любом из уровней, только через await вызовы, то current_task() вернёт None.

    Но вообще довольно странно. Эксперимент показывает, что хотя бы одна задача должна быть.
    Вот код

    import asyncio
    
    async def print_task():
        print(asyncio.current_task())
    
    
    async def foobar():
        await print_task()
    
    
    async def main():
        print('Direct call')
        await foobar()
        print('create_task')
        task = asyncio.create_task(foobar())
        await task
    
    # asyncio.run(main())  # даст такой же результат
    asyncio.get_event_loop().run_until_complete(main())

    На питоне 3.11 код выводит два объекта задачи, один создаётся run() или run_until_complete(), а другой - create_task(). Тогда получается, что получить None невозможно.
    Ответ написан
    Комментировать
  • Почему не срабатывает if? как это пофиксить?

    Vindicar
    @Vindicar
    RTFM!
    Учи основы работы с файлами в питоне и включай голову.
    Чтение и запись в файл производится по т.н. текущей позиции. При открытии файла текущая позиция стоит в начале файла, а при чтении/записи она смещается на длину прочитанного/записанного.
    А теперь смотри что ты делаешь. У тебя есть вызов fr = f.readlines(). Он построчно прочитает всё содержимое файла в список, и сохранит список в переменную fr. При этом текущая позиция окажется в конце файла - ты же прочитал всё содержимое.
    Как следствие, все дальнейшие вызовы read() и readlines() не смогут прочитать НИЧЕГО - ты уже в конце файла, дальше ничего нет. Они будут возвращать пустую строку или пустой список - а ты этого явно не ожидаешь.
    Раз уж ты читаешь весь файл в fr - то и дальше работай не с файлом, а со списком fr. Ну и проверка на chat_id у тебя кривая - что, если так совпадёт, что твой chat_id будет содержаться внутри второго значения (токен)? Такое может произойти, хоть это и маловероятно.

    Я бы посоветовал не выпендриваться со своим форматом данных в текстовике, а использовать модуль json. Он гораздо удобнее для хранения структурированной информации. А если указать правильные параметры при записи в файл, то полученный файл будет более-менее человеко-читаемым.
    Ответ написан
    2 комментария
  • Что я делаю не так Python?

    Vindicar
    @Vindicar
    RTFM!
    При установке питона обрати внимание на галочку py launcher.
    Ответ написан
    Комментировать
  • Как запустить два параллельных процесса бота: бесконечную функцию, проверяющую имеются ли обновления, и обработчики событий и сообщений?

    Vindicar
    @Vindicar
    RTFM!
    Надо хоть немножечко осознавать, как работает asyncio.
    create_task() возвращает объект класса Task, представляющий собой фоновую задачу. Эта задача уже запланирована к выполнению в рабочем цикле (loop) asyncio, и будет выполняться в фоне пока текущая корутина ожидает какой-нибудь другой операции.

    Но если тебе надо дождаться завершения работы задачи, ты можешь сделать await на этом объекте.
    Тогда текущая корутина приостановится, пока задача не завершится, и получит или возвращённое задачей значение, или выкинутое задачей исключение.
    А теперь посмотри на свой код:
    await asyncio.create_task(start_checking_price(1800))

    Ты создаёшь задачу - и тут же говоришь программе, что тебе надо дождаться её завершения!
    Ну как бы программа и делает в точности то, что ты от неё требуешь...
    Подчёркиваю красным: await asyncio.create_task(some_coro(...)) не имеет смысла практически никогда! Если тебе нужно запустить корутину и дождаться результата, делаешь просто await some_coro(...).
    А вот если тебе нужно запустить корутину параллельно текущей... Получится что-то типа такого:
    # ...
        check_task = asyncio.create_task(start_checking_price(1800))  # нету await, мы не ждём созданную задачу!
    
        try:
            await dp.start_polling()
        finally:
            check_task.cancel()  # отменяем корутину
            # внутри start_checking_price() текущий выполняемый await выкинет исключение CancelledError
            # это исключение всплывёт наружу, если мы сделаем await, и позволит отработать 
            # блокам finally, with и т.п. инструментам. Также можно явно поймать это исключение,
            # чтобы обработать отмену корутины. Но в твоём случае это не требуется.
            try:
                await check_task  # даём корутине отработать завершение
            except asyncio.CancelledError:  # ловим всплывшее CancelledError
                pass  # всё ок, никакие действия не требуются
            await my_bot.close()
    Ответ написан
    7 комментариев
  • Как получить экземпляр родителя из дочернего класса?

    Vindicar
    @Vindicar
    RTFM!
    Не надо так делать. Просто не надо.

    Лучше подумай в другую сторону - когда тебе нужно знание о полке, где стояла книга?
    Может, лучше иметь отдельную сущность - ВыдачаКниги? Вот она вполне может знать, где что стояло, и кто взял, и когда взял, и вернуть книгу на место по факту возврата.
    Ответ написан
  • Как вычислить количество записей?

    Vindicar
    @Vindicar
    RTFM!
    Прочитать все записи, разбить строку по разделителю, скормить всё в collections.Counter.
    С pandas не работал, вот пример для списков:
    from collections import Counter
    from itertools import chain
    data = [
      (1, 'old;white'),
      (2, 'old;green'),
      (3, 'old;brown'),
      (4, 'new;green'),
    ]
    # генерирует последовательность ['old', 'white'], ['old', 'green'], ...
    split_generator = (item[1].split(';') for item in data) 
    # генерирует последовательность 'old', 'white', 'old', 'green', ...
    property_generator = chain.from_iterable(split_generator)
    # исправляет регистр и удаляет пробелы - можно убрать, если не надо
    property_fixed_generator = (item.strip().lower() for item in property_generator)
    # поглощает данные из генераторов и считает вхождения
    count = Counter(property_fixed_generator)
    print(count)  # Counter({'old': 3, 'green': 2, 'white': 1, 'brown': 1, 'new': 1})
    Ответ написан
    Комментировать
  • Как указать когда нужна рекурсия а когда нет?

    Vindicar
    @Vindicar
    RTFM!
    JSON не предназначен для структур данных с циклическими ссылками. Вообще-то ты должен был словить исключение в этом случае, а не рекурсию. Очень странно, что этого не произошло.
    Тут есть две возможности:
    1. Задуматься о смысле жизни, а на кой тебе вообще обратные ссылки? Они тебе ТОЧНО необходимы? У тебя есть сценарий, когда у тебя есть ссылка на книгу, но нет необходимой ссылки на полку? Книга должна что-то знать о полке. на которой она стоит? Если без них можно обойтись, удали их. Проще жить будет. Подумай, например, что при перемещении книги с полки на полку ты должен не забыть сменить книге shelf.
    2. Посмотреть на параметр default в json.dump(). Это должна быть функция, которая принимает объект, и возвращает словарь. Ты можешь явно проверять, что объект - один из твоих датаклассов, и удалять из полученного словаря обратные ссылки. Аналогично, у json.load() есть object_hook, который позволяет задать свою логику превращения загруженных из JSON словарей в объекты. Но серьёзно, так ли нужны обратные ссылки?
    Ответ написан
  • Как реализовать Python-код, который будет распознавать речь, но будет реагировать только тогда, когда будет упомянуто определенное слово?

    Vindicar
    @Vindicar
    RTFM!
    Проверяй, содержит ли/начинается ли распознанный текст на определённое слово.
    Как - гуглится, это основы работы со строками в питоне. См. метод startswith() и оператор in. Заодно глянь методы перевода строки в другой регистр типа lower() - может помочь убрать чувствительность к регистру.
    Для начала должно хватить.
    Ответ написан
    Комментировать
  • Выполнение парсинга странцы?

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

    Vindicar
    @Vindicar
    RTFM!
    Вариант 1: Ты уверен, что запускаешь свой скрипт, используя правильное окружение?
    Что, если запустить скрипт, явно используя питон из окружения? Например,
    /путь/к/твоему/проекту/venv/bin/python3 твой_скрипт.py

    Вариант 2: имя пакета и имя импортируемого модуля могут не совпадать.
    Ответ написан
    Комментировать
  • Что не так с кодом Python?

    Vindicar
    @Vindicar
    RTFM!
    Потому что ты неверно понимаешь логику своей программы.
    Если у тебя не найдётся 1.png, вылетит исключение, и даже не будут попытки искать дальнейшие картинки - управление перейдёт в except, а затем на новую итерацию while True, где снова будет попытка искать 1.png.

    Есть и ещё ряд замечаний.
    1. На кой баклажан ты загружаешь 1.png-5.png на каждой итерации цикла? Только зря программу замедляешь. Если ты не хочешь обновлять эти файлы без перезапуска программы, то загрузи их один раз на старте.
    2. То же самое со скриншотом. Ты делаешь новый скриншот перед каждым следующим файлом - это точно хорошая идея? Вроде как надо поискать изображения на скриншоте, и только потом делать следующий.
    3. Почему ты используешь И locateOnScreen(), И matchTemplate()? Выбери ту функцию, которая лучше работает, и используй только её.
    4. Ты нифига не отслеживаешь, а что за исключение-то вылетает? Может, у тебя программа в принципе кривая, и дело не в том, что изображение не найдено. Для locateOnScreen() лови конкретно pyautogui.ImageNotFoundException. matchTemplate() исключений не кидает, так что проверяй, что locations не пуст, а имеет хотя бы один элемент. А остальные эксепшены не лови, или хотя бы выводи инфу о них в журнал работы программы.
    Ответ написан
    8 комментариев
  • В функции four_squares программа выдает ошибку как только обращается, и почему не проходит тест с этим числом 106369249365575352836589875696130383747?

    Vindicar
    @Vindicar
    RTFM!
    В питоне встроенный int поддерживает длинную арифметику, поэтому с ним можно выполнять операции даже если операнды превышают 64 бита. Но это, разумеется, медленнее, чем аппаратно-поддерживаемое число.
    Ответ написан
  • Возможно ли соединить работающий java код и так же работающий скрипт python?

    Vindicar
    @Vindicar
    RTFM!
    В принципе - конечно, возможно.
    Если один из скриптов запускает другой, через стандартный ввод/вывод.
    Если работаешь под Linux - через unix-сокет.
    Можно организовать общую область памяти через отображение файла на память (но это рискованный трюк, тут лучше использовать как можно более примитивные структуры данных).
    Ну или наиболее прямолинейное (но, возможно, чуточку более медленное) решение - через обычный сетевой сокет.

    Во всех случаях тебе придётся как-то сериализовывать свои данные на стороне отправителя, и десериализовывать на стороне получателя.
    Ответ написан
    1 комментарий