Ответы пользователя по тегу Python
  • Как сделать чтобы мой дискорд бот мог общаться с пользователями?

    Vindicar
    @Vindicar
    RTFM!
    Ну я нечто подобное делал для своего IRC бота. Идея-то простая. У тебя есть набор пар, вроде словаря: регулярное выражение, чтобы отлавливать простые фразы, и список возможных ответов. Прогоняем регулярки по входящему сообщению, ищем первую сработавшую, получаем соответствующий её список. Из списка выбираем вариант с помощью random.choice() и отправляем.

    Проблемы с этим подходом две:
    1. язык - штука очень гибкая, все варианты не перечислить в регулярке.
    2. болтливый бот быстро надоедает, поэтому лучше отвечать только на прямое обращение.
    Ответ написан
  • Какие есть способы скомпилировать Python программу в исполняемый файл?

    Vindicar
    @Vindicar
    RTFM!
    Чтобы код остался питоном - никак. Питон по природе язык с виртуальной машиной, известные мне реализации питона не делают полноценную трансляцию в машинный код. Максимум JIT.
    Но можно поискать транспиляторы, вроде cython. На главной странице репозитория есть любопытный набор ссылок.
    Ответ написан
    1 комментарий
  • Пытался написать телеграмм бота с Chat GPT. В чем ошибка?

    Vindicar
    @Vindicar
    RTFM!
    ModuleNotFoundError: No module named 'urllib3.contrib.appengine'

    Stackoverflow говорит, что это косяк в последней версии requests. Создай отдельный файл и сделай в нём только import requests - отработает или нет?

    Если нет, поставь более старую версию. Если ставил через pip, то можно указать версию явно: pip install requests==x.yy.zz. Список версий можно посмотреть на pypi.
    Ответ написан
    Комментировать
  • Как мне вывести список с экземплярами класса?

    Vindicar
    @Vindicar
    RTFM!
    В питоне есть два метода преобразования в строку: __str__() и __repr__().
    Первый преобразует объект в какую-то человекочитаемую строку. Он вызывается, если передать объект в функцию str().
    Второй обычно даёт более "техническое" представление объекта - в идеале, он показывает питоновский код, который нужно выполнить, чтобы этот объект получить. Но это требование не строгое, и никто не запрещает в __repr__() показывать что-то другое. Метод вызывается, если передать объект в функцию repr().

    Если у объекта нет __str__(), то питон попробует вызвать __repr__(). А __repr__() есть у всех объектов - он наследуется от базового object.

    Ты выводишь список целиком. У списка (list) нет метода __str__(), он использует __repr__() - и поэтому пытается вызывать repr() на твоих объектах, а repr() даже не пытается вызвать __str__(), она сразу идёт к __repr__().

    Я бы посоветовал переписать метод Deck.__str__() так:
    def __str__(self):
            return '[' + (', '.join(str(card) for card in self.mydeck)) + ']'

    Тперь он явно вызывает str() на каждой карте, а потому будет использоваться метод Card.__str__().
    Ответ написан
  • Какой командой запустить код заново в python?

    Vindicar
    @Vindicar
    RTFM!
    Почитай про цикл while и оператор break.
    Также, на будущее - не забывай оформлять код кнопкой </>.
    Чем более читаем твой вопрос и твой код, тем больше шансов получить ответ.
    Ответ написан
    Комментировать
  • Зачем функции filter методы итератора?

    Vindicar
    @Vindicar
    RTFM!
    Ну ответ на вопрос вполне очевиден:
    class filter(object):
    Это не функция, это класс. Метод __iter__ будет принадлежать экземпляру этого класса, т.е. результат вызова filter() можно будет итерировать.
    А вот почему это класс, вопрос поинтереснее. Я подозреваю, что filter() старше, чем yield и генераторы - а без них класс был бы единственным способом реализовать нужное поведение.
    Ответ написан
    2 комментария
  • Как работает замыкание в python?

    Vindicar
    @Vindicar
    RTFM!
    Мне кажется, это деталь реализации, а потому тут надо в исходники лезть. Например, для CPython можно начать с codeobject.
    Ответ написан
    Комментировать
  • Ошибка при асинхронном запросе MYSQL?

    Vindicar
    @Vindicar
    RTFM!
    Попробуй создавать курсор на каждый запрос, а не переиспользовать один и тот же.
    Ответ написан
    3 комментария
  • Как сменить одну из переменных в отдельном файле?

    Vindicar
    @Vindicar
    RTFM!
    Что значит "изменить переменную в файле"?
    Одно дело, если файл был импортирован, и тебе нужно изменить переменную в нём. Это легко.
    import names
    names.name1 = 'Абдурахман ибн Хоттаб'

    Вот только такое изменение не сохранится в файл. Если тебя это устраивает, то вопрос закрыт.

    А если ты хочешь, чтобы оно сохранялось, то всё намного хуже, потому что ты пытаешься использовать питоновский файл как файл конфигурации. Это не дело. И ещё хуже то, что твои переменные name1, name2, name3 намекают, что тебе на самом деле нужен список.
    Тогда у тебя получится что-то такое
    # names.json
    ["Дима", "Маша", "Елена"]
    
    # main.py
    import json  # чтобы легко и удобно сохранять структуры данных в файл
    import sys  # чтобы узнать, где лежит main.py, и сохранить рядом
    from pathlib import Path  # чтобы работать с путями к файлам
    
    MAIN_PY = Path(sys.argv[0])  # путь до main.py
    MAIN_DIR = MAIN_PY.parent.resolve()  # путь до папки, где лежит main.py
    CFG = MAIN_DIR / 'names.json'  # путь до файла, куда сохраняем данные
    
    with CFG.open('rt', encoding='utf-8') as cfg:  # открываем на чтение
        names = json.load(cfg)  # читаем всё содержимое файла
    # пользуемся полученными данными - списком имён
    print(names) 
    names[0] = "Абдурахман ибн Хоттаб"
    # сохраняем список обратно
    with CFG.open('wt', encoding='utf-8') as cfg:  # открываем на запись
        json.dump(  # пишем всё содержимое списка в файл
            names,  # что будет содержимым файла
            cfg,  # в какой файл записать
            ensure_ascii=False,  # чтобы не заменял кириллицу на коды символов
            indent=2,  # чтобы были красивые отступы. Если убрать, файл будет весь в одну строку.
        )
    Ответ написан
    Комментировать
  • Как правильно организовать наследование?

    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
    # если управление дошло досюда, соединение установлено
    ...  # работаем
    Ответ написан
    Комментировать