Задать вопрос
Ответы пользователя по тегу Python
  • Не работают кнопки в discord.py, что делать?

    Vindicar
    @Vindicar
    RTFM!
    @Code.bot.command()
    На момент выполнения этого декоратора класс ещё не закончил создаваться, а значит, не был присвоен имени Code.
    Почитай документацию на либу, как правильно создавать коги и каким декоратором в них отмечать команды.
    Для discord.py это @commands.command().
    Ответ написан
  • Как вы боритесь с циклическими импортами в Python?

    Vindicar
    @Vindicar
    RTFM!
    Если речь идёт об импорте только ради type hinting, то typing.TYPE_CHEKING в помощь.
    Ответ написан
    Комментировать
  • Есть ли способ аннотировать аргументы метода переменной класса?

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

    Vindicar
    @Vindicar
    RTFM!
    Ну если простейшее решение...
    Таймаут на connect(), connect() завернуть в try-except, который ловит socket.timeout и спит несколько секунд. Всё это завернуть в while True.
    Ответ написан
    Комментировать
  • Проблема с этим Введите корректный числовой код?

    Vindicar
    @Vindicar
    RTFM!
    Используй user: disnake.Member вместо id: int, удобнее будет. И почитай доки на тему.
    Ответ написан
  • В чем заключается ошибка и как ее исправить?

    Vindicar
    @Vindicar
    RTFM!
    Дополню ответ Сергей Горностаев
    cursor2.execute("SELECT sneakers_model FROM user_inventory WHERE sneakers_model = ?", (random_sneakers[0]))

    А надо
    cursor2.execute("SELECT sneakers_model FROM user_inventory WHERE sneakers_model = ?", (random_sneakers[0],))

    Без запятой у тебя просто строка передаётся, и поэтому функция каждый символ считает за отдельное значение. Вот и получается 17 символов в строке = 17 значений, а место одно.
    С запятой ты передаёшь кортеж из одной строки. Одна строка - одно место.
    Ответ написан
    Комментировать
  • Можно ли в питоне с помощью модуля ctypes (или как-то по-другому) создать указатель на любой объект?

    Vindicar
    @Vindicar
    RTFM!
    Тебе не нужен для этого ctypes, просто присвой атрибут классу.
    class Test:
        def test(self):
            print(f"It's a-me, {self!r}!")
    
    
    t = Test()
    t.test()
    
    def alt(instance):
        print(f"My name is {instance}. You killed my parent process. Prepare to die.")
    
    
    Test.test = alt
    
    t.test()


    Правда, с builtin классами такое не прокатит.
    Ответ написан
  • Как работает annotated-types в пределах Pydantic?

    Vindicar
    @Vindicar
    RTFM!
    Насколько я понял, annotated-types просто задаёт стандарт для описания правил валидации полей, и способ получения этого описания для класса. А уж как это описание будет использоваться, должна решать конкретная библиотека, которая этому стандарту следует. Т.е. annotated-types сам по себе ничего не проверяет.
    Впрочем, в тестах у них есть примитивный пример реализации.
    Ответ написан
    Комментировать
  • Можно ли задать несколько вариантов обработки для одного типа исключения?

    Vindicar
    @Vindicar
    RTFM!
    Подумай сам. Как питон поймёт, какой сценарий нужно вызывать? У него фактически есть только два ориентира - блок try, в котором произошло исключение, и класс исключения.
    Ответ написан
    Комментировать
  • Почему не выводит Print("TEST")?

    Vindicar
    @Vindicar
    RTFM!
    А почему ты пытаешься запустить проект как unit test? Запускай его по-нормальному.
    Ответ написан
    5 комментариев
  • Sqlite3, OperationalError: unable to open database file, как обойти эту ошибку?

    Vindicar
    @Vindicar
    RTFM!
    Путь к файлу у тебя относительный, т.е. он будет зависеть от текущего рабочего каталога. А тот, в свою очередь, зависит от того, как ты запускаешь скрипт, и может меняться в ходе работы скрипта.
    Так что если нужен путь именно относительно скрипта, используй pathlib.
    from pathlib import Path
    from sys import argv
    
    script_dir = Path(argv[0]).parent.resolve()  # путь к каталогу скрипта
    db_path = script_dir / 'basa' / 'users.db'  # путь к файлу в подкаталоге
    Ответ написан
    1 комментарий
  • Как в python разделить строку через разделитель?

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

    Vindicar
    @Vindicar
    RTFM!
    Я не понял зачем ты пытаешься подключиться к серверу в отдельном потоке. Если это критично, почитай про неблокирующие операции на сокетах, и как ими пользоваться.

    Да ещё и глотаешь исключения. Очень не советую писать except: pass, у тебя вместо сколь-нибудь понятного сообщения об ошибке программа будет молча не работать.

    В любом случае ты делаешь только одну попытку подключения. Поток выполнит try_connect() один раз и завершит работу. Отсюда и наблюдаемое поведение - клиент не переконнектится, потому что в коде это не прописано.
    Ответ написан
    Комментировать
  • Выдает ошибку Traceback (most recent call last) что делать?

    Vindicar
    @Vindicar
    RTFM!
    У класса TeleBot нет метода edited_message_text(). Ты неправильно написал название.
    Ответ написан
  • Как сделать что бы на экран вывелись повторные значения, которые дальше в столбце?

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

    Более практичным подходом было бы получать сразу весь диапазон Логи!A:F, и перебирать его строки. Тогда и индекс считать не потребуется, у тебя в текущей строке будет информация по одному и тому же юзеру. Проверяешь нулевой элемент строки на нужное имя, если совпало - вытаскиваешь из последующих элементов нужную информацию.
    Ответ написан
    2 комментария
  • Бот не отвечает на команды | disnake?

    Vindicar
    @Vindicar
    RTFM!
    RTFM!
    Why does on_message make my commands stop working?
    Overriding the default provided on_message forbids any extra commands from running. To fix this, add a bot.process_commands(message) line at the end of your on_message.


    disnake, ЕМНИП - форк discord.py, так что наверняка это верно и для него.
    Ответ написан
    Комментировать
  • Как запустить две функции параллельно в asyncio?

    Vindicar
    @Vindicar
    RTFM!
    Намудрил-то, намудрил-то...
    background_func() сделай асинхронной, run_in_executor() в ней нафиг не нужен, можно будет просто сделать await bot.send_message(...).
    time.sleep(), соответственно, меняешь на await asyncio.sleep().
    executor.start_polling() вызывай прямо в теле программы, без выкрутасов.

    Для запуска функции при старте бота опиши её как
    async def bot_startup(dp: Dispatcher):
    и передай её в параметре on_startup при вызове start_polling().
    А внутри bot_startup уже делай что нужно, например, asyncio.create_task(background_func()).
    Обрати внимание, без await - тогда background_func() будет работать параллельно боту.
    Ответ написан
    2 комментария
  • Как сделать так, чтобы данные, которые я пишу в тг бота, заполняли сперва первую строчку в таблице postgre?

    Vindicar
    @Vindicar
    RTFM!
    Почитай хотя бы про основы реляционных БД.
    У каждой таблицы должен быть первичный ключ - иными словами, такое поле/комбинация полей, которая будет уникальной для каждой записи.
    Тогда алгоритм будет такой: спрашиваешь пользователя, какую запись он хочет редактировать, запоминаешь её ключ, затем переходишь в режим редактирования, где поочерёдно спрашиваешь значения столбцов.
    Подразумевается, что ты знаешь, как сделать сценарий, чтобы бот последовательные сообщения обрабатывал по-разному. Если не знаешь - читай, как реализуется finite state machine (FSM) в выбранной тобой библиотеке.
    Ну и да:
    data = message.text.strip()
    cur.execute(f"INSERT INTO {tableName} ({column_name}) VALUES ('{data}')")

    Это - готовая SQL инъекция. И если вставку tableName и column_name еще можно оправдать (хотя ты их тоже не проверяешь на допустимость), то данные так вставлять нельзя. Есть правильный способ.
    Ответ написан
    Комментировать
  • Как в питоне обеспечить контроль целосности данных?

    Vindicar
    @Vindicar
    RTFM!
    С переменными так не прокатит. А вот с полями класса - при желании можно, если использовать property.
    Базовая идея простая - пусть сеттер свойства производит валидацию.
    Например, так
    class Person:
        def __init__(self, name: str):
            self._name: str = ''
            self.name = name
        
        @property
        def name(self) -> str:
            return self._name
        
        @name.setter
        def name(self, value: str) -> None:
            if not value:
                raise ValueError('Must not be empty')
            self._name = value

    Но писать такой бойлерплейт быстро надоест. Поэтому можем попробовать обобщить процесс.
    Например, так
    from typing import TypeVar, Type, Any, Annotated, Callable, Dict, get_args, get_origin
    
    T = TypeVar('T')
    ValidationRule = Callable[[Any], bool]
    ValidationRules = Dict[str, ValidationRule]
    
    class ValidatedProperty:
        """Экземпляры этого класса будут свойствами в валидируемых классах, и будут заниматься валидацией."""
        def __init__(self, name: str, storagename: str, rules: ValidationRules):
            self.name = name  # как называется свойство
            self.storagename = storagename  # где его хранить
            self.rules = rules  # какие правила применять
    
        def __get__(self, instance, owner=None):
            return getattr(instance, self.storagename)  # при чтении просто возвращаем свойство
        
        def __set__(self, instance, value):  # при записи валидируем
            for message, rule in self.rules.items():  
                if not rule(value):  # если правило нарушено, выкидываем исключение с сообщением
                    raise ValueError(f'{instance.__class__.__name__}.{self.name}: {message}')
            setattr(instance, self.storagename, value)
    
    
    def validated(klass: Type[T]) -> Type[T]:
        """Декоратор для валидируемых классов."""
        for name, annot in klass.__annotations__.items():  # проверяем список аннотаций в классе
            base = get_origin(annot) or annot
            if base is not Annotated:  # нас интересуют только те, которые помечены как Annotated
                continue
            args = get_args(annot)
            rules = [arg for arg in args if isinstance(arg, dict)]
            if not rules:  # и только если один (любой) из аргументов Annotated - словарь
                continue
            # в этом случае мы считаем, что словарь содержит правила валидации, и создаём свойство класса
            setattr(klass, name, ValidatedProperty(name, f'_{name}', rules[0]))
        return klass  # не забываем вернуть изменённый класс!
    
    
    @validated
    class Person:
        name: Annotated[str, {'must not be empty': lambda v: bool(v)}]
        age: Annotated[int, {'must be positive': lambda v: v > 0}]
    
        def __init__(self, name: str, age: int):
            self.name = name  # валидация отработает уже здесь
            self.age = age  # валидация отработает уже здесь
        
        def __repr__(self) -> str:
            return f'Person(name={self.name!r}, age={self.age!r})'
    
    try:
        Person('John Doe', 23)  # отработает успешно
    except Exception as err:
        print('Failed to create person 1')
        print(f'{err.__class__.__name__}: {err!s}')
    else:
        print('Person 1 created')
    
    try:
        Person('', 23)  # выкинет исключение
    except Exception as err:
        print('Failed to create person 2')
        print(f'{err.__class__.__name__}: {err!s}')
    else:
        print('Person 2 created')
    
    try:
        Person('Jane Doe', -23)  # выкинет исключение
    except Exception as err:
        print('Failed to create person 3')
        print(f'{err.__class__.__name__}: {err!s}')
    else:
        print('Person 3 created')
    
    p = Person('John Doe', 23)
    try:
        p.name = ''  # выкинет исключение
    except Exception as err:
        print('Failed to modify person')
        print(f'{err.__class__.__name__}: {err!s}')
    
    try:
        p.age = 0  # выкинет исключение
    except Exception as err:
        print('Failed to modify person')
        print(f'{err.__class__.__name__}: {err!s}')
    
    try:
        p.age = 24  # отработает успешно
    except Exception as err:
        print('Failed to modify person')
        print(f'{err.__class__.__name__}: {err!s}')
    
    print(p)
    print(vars(p))


    Это, конечно, велосипед, и пользоваться им я бы не посоветовал. Для валидации есть библиотеки типа pydantic.
    Плюс, как было указано выше, не всё и не всегда имеет смысл валидировать...

    А для работы с БД лучше использовать ORM. SqlAlchemy популярна, но есть и более простые, например, peewee или ponyorm.
    Ответ написан
    Комментировать
  • Как вернуть значения из синхронного колбека в corotine несколько раз?

    Vindicar
    @Vindicar
    RTFM!
    Я вижу два потенциальных источника проблем.
    1. Ты говоришь, что библиотека будет дёргать callback при изменении значения свойства. А когда она будет это делать?
    Ей ведь нужно выполнить для этого какой-то код, причём наверняка синхронный. Пусть какой-то метод, который проверит очередь событий, извлечёт оттуда новые и дёрнет соответствующие callbak'и. Этот код точно вызывается?
    2. Ты делаешь await iface.call_method('bla'). Ты уверен, что обновление свойства произойдёт после завершения await? Если оно произойдёт до, то твой вызов wait_property() не увидит обновлений. Возможно, стоит вешать callback до вызова call_method()?
    Ответ написан
    Комментировать