Задать вопрос
  • При запуске бота выдает ошибку AttributeError: 'NoneType' object has no attribute 'create_task' как исправить?

    Vindicar
    @Vindicar
    Тогда спроси на фрилансе? Там скорее сделают, чем тут кого-то уговаривать.
  • Как реализовать отправку уведомлений ботом при соблюдении условий?

    Vindicar
    @Vindicar
    NoKit, Смотри, await run_check() остановит вызывающую корутину, так как run_check() содержит бесконечный цикл (а потому никогда не вернёт значение).
    Нужно сделать пару правок.
    1. использовать task = asyncio.create_task(run_check()). Это позволит запустить корутину, не дожидаясь её выполнения.
    2. Добавить условие прекращения цикла. Например, если сохранили task из пункта выше, можно сделать task.cancel() чтобы выкинуть внутри run_check() исключение CancelledError.
  • Как правильно список загрузить в базу данных MySQL через Python?

    Vindicar
    @Vindicar
    val = [(4, 5))]

    Это не может работать, синтаксис кривой. Приведи реальный код.
  • Как тут сделать insert?

    Vindicar
    @Vindicar
    Глеб Лукашонок, можешь использовать мой вариант. Тогда всеми вопросами экранирования займётся прослойка работы с БД, и тебе не придётся помнить "а можно ли в эту функцию передавать параметры с апострофами?"
  • Как тут сделать insert?

    Vindicar
    @Vindicar
    Akina, если используется литерал, то запрос можно и захардкодить без форматирования.
    А если это значение откуда-то получается, то это мало чем отличается от пользовательского ввода. Не говорю уж про ситуацию, когда ранее захардкоженное значение рефакторится в пользовательский ввод без исправления способа формирования запроса.
    Так что тут лучше перебдеть чем недобдеть.
    По мне так есть только три сценария для ручного формирования запроса: кастомный поиск (по заранее неизвестному набору условий), кастомный порядок сортировки, и использование оператора IN со списком заранее неизвестного размера (последний случай тоже реализуется через плейсхолдеры, но без синтеза запроса не обойтись).
  • Windows распределяет потоки Python по ядрам?

    Vindicar
    @Vindicar
    SKEPTIC, Я не думаю, что питон предоставляет такое апи - оно очень зависит от ОС. Но если прямо позарез нужно, можно попробовать дёрнуть из питона WinAPI, а именно SetProcessAffinityMask(). Достучаться до WinAPI вполне реально.
  • Какой подход для фильтрации таблиц лучше?

    Vindicar
    @Vindicar
    denislysenko, нет, я не понял о чём речь.
    Максимум, что я могу поинтересоваться: если нужна переносимость программы на уровне "скопировали папку", почему используешь mysql? Почему не sqlite, который в питоне есть из коробки и хранит БД в одном файле?
  • Какой подход для фильтрации таблиц лучше?

    Vindicar
    @Vindicar
    denislysenko, минутку. Клиент-сервер подразумевает сетевое соединения, типа сокетов или чего-то более высокоуровневого. И потом, что будет является клиентом, а что сервером? Вы - клиент, а сторонний сервер БД - сервер? Консольная утилита - клиент, и ещё одна - сервер, связанные протоколом собственной разработки?
    Уточни задание, потому что я БЕЗ ПОНЯТИЯ что от тебя хотят.
  • Во время произношения ассистент говорит "текст"None, как можно исправить?

    Vindicar
    @Vindicar
    UMFUCHI, хосспади, я имел ввиду просто
    if __name__ == '__main__':
        while True:
            command = listen_command()
            vcl.run_command(command)

    Если я верно понял твой код, это должно было сработать.

    Если же это не работает, проверь следующее (можно с помощью пары отладочных print):
    0. Выводится ли сообщение об ошибке? Если нет, то какие симптомы? Бот просто игнорирует всё?
    1. Попробуй временно заменить listen_command() на input(). Если при вводе с клавиатуры команды распознаются, дело в распознавании голоса?
    2. Что лежит в vcl.actions на момент перед while True? Там должен быть список из нескольких элементов, по одному на каждую из отмеченных декоратором @vcl.on() функций.
    3. Проверь цикл for внутри run_command(). Что приходит в text? Срабатывает ли хоть один раз условие if predicate()?
  • Во время произношения ассистент говорит "текст"None, как можно исправить?

    Vindicar
    @Vindicar
    UMFUCHI, прочитай мои сообщения ещё раз. Внимательно. Я это уже объяснял.

    ---
    Ну а чтобы скормить боту распознанную строку:

    vcl.run_command('привет') #сюда можно подставить выхлоп распознавателя речи
    ---
    1. Работа с распознавателем речи. run_command() принимает сказанную пользователем строку, ты должен её предоставить как параметр при вызове run_command(). По сути, vcl.run_command() - это аналог твоего do_this_command().
    ---

    Сравни с твоим кодом

    if __name__ == '__main__':
        while True:
            command = listen_command()
            vcl.run_command() # <--- чего-то не хватает?
  • Во время произношения ассистент говорит "текст"None, как можно исправить?

    Vindicar
    @Vindicar
    UMFUCHI, перечитай пункт 1 коммента выше.
    По сути, vcl.run_command() - это аналог твоего do_this_command().


    Ещё добавлю: возможно, стоит либо изменить проверку на вхождение подстроки, либо добавить поддержку регулярных выражений.
    Потому что команда "напиши привет" будет выполнена либо как "напиши" либо как "привет", в зависимости от того в каком порядке объявлены функции.
  • Как сделать чтобы сообщение Telegram обновлялось пока выполняется другой скрипт?

    Vindicar
    @Vindicar
    InternetMaster, asyncio.sleep() это из asyncio, которая является частью стандартной библиотеки.
  • Во время произношения ассистент говорит "текст"None, как можно исправить?

    Vindicar
    @Vindicar
    UMFUCHI, от твоего старого кода потребуются только две вещи.
    1. Работа с распознавателем речи. run_command() принимает сказанную пользователем строку, ты должен её предоставить как параметр при вызове run_command(). По сути, vcl.run_command() - это аналог твоего do_this_command().
    2. Функция say_message() остаётся неизменной.

    Всё, что было в ветках if-elif твоего старого кода распихиваешь по отдельным функциям, как я показал в примере. Одна ветка - одна функция. Условие ветки (точнее, искомый текст) идёт в декоратор функции.
    Например:
    if "привет" in message :
            say_message("Здравствуйте, хозяин!")

    Превращается в:
    @vcl.on('привет')
    def hello(text):
      return "Здравствуйте, хозяин!"
  • Как сделать достижения в асинхронном боте телеграм(aiogram)?

    Vindicar
    @Vindicar
    black_dis, возможно, но тогда эта функция будет непрерывно перелопачивать базу и проверять все возможные ачивки для всех пользователей поочерёдно. В том числе те, которые зависят от стат, меняющихся раз в год. В том числе для пользователей, которые уже сто лет не появлялись.
    Мне кажется, это намного хуже. В принципе, тебе никто не мешает реализовать вышеописанную проверку как асинхронный таск, запускающийся параллельно обработчику события, особенно если запросы к БД тоже будут асинхронными. Она же не будет связана с логикой основного обработчика...
  • Как исправить код?

    Vindicar
    @Vindicar
    UMFUCHI, В варианте, который я привел тут - никуда, он этого не предусматривает. Он вообще ничего не предусматривает кроме текстовых ответов (бот-говорилка).

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

    Vindicar
    @Vindicar
    black_dis, ну пример. Мы хотим давать ачивку, когда пользователь наберёт 100 сообщений на сервере.
    Тогда при реакции на сообщение мы должны изменить соответствующую стату - сделать stat_bump() с указанием id пользователя, статистики, которая нас затронула (в нашем случае я её назвал messages_sent) и насколько мы эту стату увеличиваем (в нашем случае на 1).
    И вот этот момент и является оптимальным для проверки на получение новых ачивок, как раз когда стата изменилась. Мы можем хранить (в stat_checks) для каждой интересующей нас статы ряд проверок, и ачивок которые они дают, и прогнать эти проверки чтобы понять, какие ачивки будут у пользователя.
    Единственное, нужно учесть, какие ачивки уже есть, иначе за каждое сообщение после 100 пользователь будет снова и снова получать ачивку X)
  • Как сделать достижения в асинхронном боте телеграм(aiogram)?

    Vindicar
    @Vindicar
    black_dis, Как вариант, можно оформить проверку на достижение сразу после изменения статы, ответственной за это достижение. Например, таким образом.

    stat_checks = {
      #проверяемая стата
      'messages_sent': [
        #функция или лямбда для проверки ачивки, id ачивки
        ( (lambda v: v > 100), 'achievement_100_messages'),
      ],
      'voicechat_time': [
        #...
      ],
    }


    Тогда у вас будет функция для повышения статы типа
    def stat_bump(user_id, stat_id, delta):
      #выполняем запрос UPDATE/INSERT для статы stat_id
      query(...)
      #узнаем текущее значение статы stat_id
      stat_value = ...
      #узнаем ачивки пользователя
      achievements  = ...
      for predicate, achiev in stat_checks.get(stat_id, []):
        if predicate(stat_value) and (achiev not in achievements):
          #набрал стату на ачивку, но ачивки такой ещё нет!
          give_achievement(achiev, user_id)
  • Как отправить изображение используя socket?

    Vindicar
    @Vindicar
    Zero None, ну UDP - штука такая. В локалке проблем может и не возникнет.
    Кроме того, так как нет постоянного соединения, придётся добавлять к отправляемому фрагменту изображения метаданные: сколько еще пакетов ожидать, какой номер пакета... в общем, половину TCP реализовать придётся. =)
    Именно поэтому я и посоветовал переделать скрипт, а не искать ошибку в коде.
  • Какой подход для фильтрации таблиц лучше?

    Vindicar
    @Vindicar
    denislysenko, я бы написал класс для фильтрации, а потом уже функцию для форматирования.
    class Filter:
      def __init__(self):
        self.year_to = None
        self.year_from = None
        self.genres = set()
        #ну и так далее
      def check(self, obj) -> bool:
        #делаем цепочку условий отсева вида "условие_актуально and условие_не_выполняется"
        #ну или как там у тебя к году фильма обратиться?
        if self.year_to is not None and obj['year'] > self.year_to: 
          return False
        if self.year_from is not None and obj['year'] < self.year_from:
          return False
        #obj['genres'] должен быть коллекцицей жанров, а не строкой вида жанр1|жанр2
        if self.genres and self.genres.isdisjoint(obj['genres']): 
          return False
        #и так далее, столько условий, сколько надо
        #а если дошли до конца, то фильм подошел
        return True

    Использовать класс тоже просто.
    flt = Filter()
    flt.genres = set(['Drama', 'Romance']) #или вытаскиваешь жанры из аргументов командной строки
    flt.year_from = 2010
    #бум, список подходящих под критерии фильмов
    filtered = list(filter(flt.check, movies))
    #если нужно N лучших, то сортируешь по рейтингу
    filtered.sort(key = lambda m: ... )
    filtered = filtered[0:N]

    Осталось вывести в красивом формате.
    Вообще, я бы посоветовал поменять алгоритм парсинга и сделать dataclass для фильма, т.е. хранить в списке не кортежи а объекты. Было бы сильно проще жить.
    from dataclasses import dataclass
    @dataclass
    class Movie:
      #__slots__ позволяет сэкономить память, если набор атрибутов объекта известен заранее и неизменен.
      #полезно для маленьких объектов, которые будут существовать в большом количестве
      __slots__ = ('id', 'name', 'year', 'genres', 'rating')
      id: str #int?
      name: str
      year: int
      genres: set
      rating: float
    #конструктор датакласс сгенерирует сам

    Тогда нужно переписать парсер, чтобы он по каждой строке создавал новый объект Movie, и складывал их в массив. Затем можно будет заполнить рейтинги фильмов (при создании Movie задашь нулевые).
    А потом уже заниматься фильтрацией и прочим.