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

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

    Vindicar
    @Vindicar
    RTFM!
    А зачем ты делаешь data:? Не проще сделать <img src="/photo" />?
    Ну и да, ты говоришь, что у тебя есть переменная encoded_image - а где она? Ты не делаешь base64 кодирование, хотя и заявляешь, что делаешь.
    Ответ написан
    3 комментария
  • Как скомпилировать файл python в exe?

    Vindicar
    @Vindicar
    RTFM!
    Убедись, что каталог, где лежит pyinstaller.exe (скорее всего каталог установки питона, подкаталог Scripts), находится в переменной окружения PATH, или указывай полный путь до него.

    И да, это не компиляция, это упаковка. Разница значительная.
    Ответ написан
  • Как вывод команды help в терминал передать в переменную?

    Vindicar
    @Vindicar
    RTFM!
    help() выводит doc-string переданного объекта. Обычно этот doc-string лежит в атрибуте __doc__.
    Так что можно сделать куда проще, чем подсовывать что-то вместо stdout:
    help_text = getattr(obj, '__doc__', None)
    В help_text будет None или строка документации.
    Ответ написан
    Комментировать
  • Как запускать и работать в разных py файлаз через тг бота?

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

    Vindicar
    @Vindicar
    RTFM!
    Это можно сделать, но в 99% случаев это не нужно делать. Во-первых, пользователь может ввести строку, которая не является корректным идентификатором. Во-вторых, появляется риск нечаянно перезаписать переменную, которую мы не хотели трогать.
    Вместо этого следует использовать словарь (dict), где ключ - имя "переменной", а значение - её содержимое. Это куда более контролируемо.
    Нет, я хочу выстрелить себе в ногу, и санитары меня не остановят!

    Функция globals() возвращает словарь глобальных переменных, а locals() - словарь локальных.
    При этом эти словари - не копии, а, можно сказать, оригиналы. Добавишь в них новый ключ - появится новая переменная. Вот пример в интерактивной консоли питона:
    Python 3.11.7 (tags/v3.11.7:fa7a6f2, Dec  4 2023, 19:24:49) [MSC v.1937 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> l = locals()
    >>> l['x'] = 1
    >>> x
    1
    >>>

    Ответ написан
    Комментировать
  • Как асинхронно создать QR код?

    Vindicar
    @Vindicar
    RTFM!
    Потому что создание QR-кода - это вычислительная операция, а не операция ввода/вывода. Вычислительные операции не имеет смысла делать асинхронными. Если создание QR-кода занимает у тебя достаточно длительное время, чтобы это было проблемой для остальной программы - засунь этот код в поток через run_in_executor(). Тогда у тебя будет асинхронный future-объект, который можно awaitить как обычно.
    Ответ написан
    4 комментария
  • Как сделать закрытие окна по названию 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})
    Ответ написан
    Комментировать