Задать вопрос
  • Бот рандомно выбирает вопрос, но проверяет по ответам для 1 вопроса, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    if x == 1:
        @bot.message_handler(content_types="text")
        def send(message):
            ...

    Так работать НЕ будет. Ты явно не очень понимаешь, что делаешь.

    1. Должна быть только одна функция, декорированная как @bot.message_handler(content_types="text"). Если их несколько, отработате только одна.

    2. Ты должен хранить сведения:
    - Какой вопрос был последним задан тому или иному пользователю
    - Какие вопросы были уже заданы тому или иному пользователю
    В рамках обучения их можно хранить в словаре, но в реальном боте потребуется постоянное хранилище (например, БД), в котором эти сведения пережили бы перезапуск бота

    3. Внутри обработчика @bot.message_handler ты должен получить ID пользователя, отправившего сообщение, взять из описанного выше хранилища номер последнего заданного вопроса (если есть), и уже на основании этого номера судить о том, правильный ли ответ.
    Ответ написан
  • Как склеить программно 2 изображения?

    Vindicar
    @Vindicar
    RTFM!
    Ну базовый вариант, если используешь OpenCV, ориентируйся на поиск локальных особенностей, а потом findHomography(), чтобы найти такое преобразование, которое переведёт точку на первом кадре в эквивалентную точку на втором. После этого warpPerspective(), чтобы преобразовать первый кадр в систему координат второго. Это должно совместить общие точки.

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

    Vindicar
    @Vindicar
    RTFM!
    Для начала скажи, какую задачу ты пытаешься решить.
    Для случая с одноразовым потоком-воркером, тебе не нужна глобальная переменная. Достаточно класса.
    import threading
    
    class MyWorkerThread(threading.Thread):
        def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
            # поток не должен их менять!
            super().__init__()
            self.arg1 = arg1
            self.arg2 = arg2
            self.result: t.Optional[float] = None
        def run(self):
            time.sleep(10) # имитируем длительную работу
            self.result = self.arg1 + self.arg2

    И тогда ты можешь его использовать так:
    worker = MyWorkerThread(42, 69)
    worker.start()
    while True: 
        if worker.is_alive():  # проверяем, жив ли поток
            # делаешь ещё что-то, пока поток работает
            print('Still working...')
            time.sleep(0.5)
        else:
            # поток завершился, даём знать пользователю.
            print(f'Done! Result is {worker.result}!')
            break # выходим из цикла

    Если же тебе нужно просто дождаться конца потока, ничего не делая в процессе, можно сделать просто worker.join()

    Сложности начинаются, когда тебе нужно взаимодействовать с длительным потоком. Усложним пример:
    import threading, queue
    
    class MyWorkerThread(threading.Thread):
        def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
            # поток не должен их менять!
            super().__init__()
            self.arg1 = arg1
            self.arg2 = arg2
            self.result: t.Optional[float] = None
            self.progress = queue.Queue()
        def run(self):
            for i in range(10):
                time.sleep(1) # имитируем длительную работу
                self.progress.put(i/10) # сообщаем о прогрессе
            self.result = self.arg1 + self.arg2
            self.progress.put(1.00)

    Тогда код использования изменится следующим образом:
    worker = MyWorkerThread(42, 69)
    worker.start()
    while True: 
        if worker.is_alive():  # проверяем, жив ли поток
            # делаешь ещё что-то, пока поток работает
            try:
                progress = worker.progress.get(block=True, timeout=0.5)
            except queue.Empty: # поток ничего не сообщил
                print('Still working...')
            else:
                print(f'Still working... {progress:.0%}')
                worker.progress.task_done() # один вызов task_done() на один успешный вызов get()!
        else:
            # поток завершился, даём знать пользователю.
            print(f'Done! Result is {worker.result}!')
            break # выходим из цикла

    Если тебе нужно передать потоку новые задания, то можешь использовать ещё одну queue.
    Ответ написан
    Комментировать
  • Как выполнять функцию каждую минуту в определенный интервал времени aioschedule?

    Vindicar
    @Vindicar
    RTFM!
    Вариант А. Выполнять каждые 5 минут, внутри функции проверять текущее время. Ничего не делать, если время не в заданном интервале.

    Варинат Б. Запланировать две функции. Одна, в 10:00, запустит через asyncio.create_task() простую зацикленную функцию, которая будет вызывать твою функцию, а потом делать await asyncio.sleep(300). Ссылку на задачу, возвращённую create_task(), надо будет сохранить в глобальную переменную.
    Другая функция, в 14:00, остановит эту задачу.

    Вариант А проще, и надёжнее в плане ситуации, когда программа запущена в промежуток между 10:00 и 14:00.
    Ответ написан
  • Multiprocessing.Process OSError: [WinError 87] Параметр задан неверно, что делать?

    Vindicar
    @Vindicar
    RTFM!
    Ну так тебе же говорят:
    _pickle.PicklingError: Can't pickle <function <lambda> at 0x00000122F23CEB00>: attribute lookup <lambda> on __main__ failed

    Для передачи данных в соседний процесс они сериализуются через модуль pickle. А сериализовываться так может далеко не всё.
    Если тебе нужно скинуть в соседний процесс код... это проблема. Может, получится скинуть словарь с локальными переменными, строку с кодом, и вычислить эту строку через eval() уже "на месте".
    Альтернативно, просто замени лямбду на нормальную функцию, и попробуй передать либо её, либо имя этой функции, чтобы дочерний процесс сам её взял из globals() или еще откуда.
    Ответ написан
    Комментировать
  • Как решить данную задачу на python?

    Vindicar
    @Vindicar
    RTFM!
    Вычисляешь корень, вычисляешь первый элемент последовательности - x, вычисляешь второй элемент (x + x/x) / 2.
    Потом в цикле, пока модуль (abs) разницы корня и последнего вычисленного элемента больше заданной точности, повторяешь вычисление. Предыдущему элементу previous присваиваешь последний элемент last, а последний элемент last вычисляешь как last = (x + x/previous) / 2. Считаешь итерации.
    Когда выйдешь из цикла, выводишь номер итерации, последний вычисленный элемент last, его отличие от реального корня.
    Ответ написан
  • Не работает replace в голосовом ассистенте?

    Vindicar
    @Vindicar
    RTFM!
    Ну ты же явно какую-то глупость делаешь.
    if cmd == "sreachyoutube":
            search_term = cmd.replace("Кеша видео", " ")

    Если в переменной cmd лежит строка sreachyoutube(!), то там по определению не может содержаться подстроки "Кеша видео".
    Ответ написан
    8 комментариев
  • Как узнать находятся ли все элементы списка в другом списке?

    Vindicar
    @Vindicar
    RTFM!
    Преврати первый список и второй список в множества. Если первое множество является подмножеством (issubset()) второго, то условие выполнилось.
    Если есть возможность строить множество одновременнео с первым списком, это упростит задачу.
    Ответ написан
    1 комментарий
  • Как сделать таймер в python?

    Vindicar
    @Vindicar
    RTFM!
    1. При получении команды получить текущее время.
    2. Проверить в хранилище (словарь в памяти, база данных, не принципиально) когда этот человек посылал команду в прошлый раз.
    3а. Если интервал времени достаточно длинный, выполнить команду и сохранить текущее время в хранилище.
    3б. Если интервал времени недостаточно длинный, дать предупреждение/забанить/застрелиться.
    Подробности

    Что за команда, о чём речь, каким кодом это реализовано... гадать никто не собирается.
    Ответ написан
    Комментировать
  • Где ошибка в коде?

    Vindicar
    @Vindicar
    RTFM!
    Ну что, ошибка правильно тебе говорит.
    def __init__(self, replaybtn):
            self.replaybtn = replaybtn

    Ты говоришь, что конструктор твоего класса Dinobot принимает один параметр, replaybtn.
    А ты ему потом передаёшь два параметра: (470, 440), (202, 442)
    Ответ написан
    2 комментария
  • Как объединить в проверке (if call.data == '') несколько параметров?

    Vindicar
    @Vindicar
    RTFM!
    if call.data == 'apple' or 'melon':    #Вот в этом месте проблема

    Ещё один ботописатель с этой проблемой. Вот откуда такое упорное желание дословно переводить с русского на питон?

    Правильно:
    if call.data in ('apple', 'melon'):
    Ну или так:
    if call.data == 'apple' or call.data == 'melon':

    То, что ты написал, расшифровывается как
    if (call.data == 'apple') or ('melon' != ''):
    что эквивалентно
    if (call.data == 'apple') or True:
    А x or True всегда даст True, так же как x and False всегда даст False.
    Так что получается в итоге
    if True:

    Учи основы языка - потом уже берись за ботов.
    Ответ написан
    1 комментарий
  • Как сделать перенос строк в парсере?

    Vindicar
    @Vindicar
    RTFM!
    Так же, как и всегда. Добавь символ "\n" в конец выводимой строки.
    Ответ написан
    2 комментария
  • Не добавляется столбец в sqlite3, что делать(срочно, пожалуйста)?

    Vindicar
    @Vindicar
    RTFM!
    Что лежит в переменной channel_id? Это строка? Если это строка, она точно содержит только символы, допустимые для имени столбца? Ты это проверил, или понадеялся на авось?

    А вообще, если ты вынужден делать ALTER TABLE на ходу, у тебя большие проблемы с архитектурой БД. Дальше будет только хуже.
    Лучше опиши задачу, которую пытаешься решить (хотя я догадываюсь, что это очередной чудо-бот).
    Ответ написан
  • Как решить пример в Python, который находится как string в переменной?

    Vindicar
    @Vindicar
    RTFM!
    Тупой способ: использовать eval(), но это очень рискованно! Если данные приходят извни, атакующий может вписать туда почти любой питоновский код. Потом не плачь, что тебя не предупреждали.

    Умный способ, на примере (-5 * 3) - 2:
    1. Разбить строку на осмысленные токены : число, оператор и т.п. Для каждого токена хранить его тип и значение. Получим список в духе:
    [('parenthesis', '('), ('operator', '-'), ('number', '5'), ('operator', '*'), ('number', '3'), ('parenthesis', ')'), ('operator', '-'), ('number', '2') ]

    Тут ушли все пробелы.
    2. Подправить унарные операторы. Операторы "+" и "-", следующие за началом строки, открывающей скобкой или другим оператором, являются унарными (с одним аргументом), а не бинарными (с двумя). Их стоит обозначить по другому, чтобы не путать. Получим такое (смотри на второй токен):
    [('parenthesis', '('), ('operator', 'unary-'), ('number', '5'), ('operator', '*'), ('number', '3'), ('parenthesis', ')'), ('operator', '-'), ('number', '2') ]

    3. Преобразовать из инфиксной нотации (2 + 3) в постфиксную (2 3 +). Для этого есть железнодорожный алгоритм Дейкстры, он гуглится. В постфиксной нотации всё решается куда проще, так как ей не нужны скобки. Наш пример запишется как 5 unary- 3 * 2 -
    [('number', '5'), ('operator', 'unary-'), ('number', '3'), ('operator', '*'),  ('number', '2'), ('operator', '-')]

    4. Решить пример. Алгоритм очень простой. У нас есть список аргументов, поначалу он пуст. Идём по списку токенов (в постфиксной нотации):
    а. Если токен - число, поместить его в конец списка аргументов, перейти к следующему токену.
    б. Если токен - унарный оператор, взять и удалить последний элемент из списка, применить к этому элементу оператор, результат добавить в конец списка.
    в. Если токен - бинарный оператор, взять и удалить последние 2 элемента из списка, применить к ним оператор (не перепутай порядок аргументов!), результат добавить в конец списка.
    Всё! Когда токены кончатся, у тебя в списке аргументов должно быть ровно одно число - это и будет ответ.
    На нашем примере:
    [('number', '5'), ('operator', 'unary-'), ('number', '3'), ('operator', '*'),  ('number', '2'), ('operator', '-')]

    1. Число "5": список аргументов [ 5 ]
    2. Унарный минус: берем 5 из списка, применяем оператор, кладем результат назад. Список аргументов [ -5 ]
    3. Число "3": список аргументов [ -5, 3 ]
    4. Оператор *: берем -5 и 3 из списка, применяем оператор, кладём результат назад. Список аргументов [ -15 ]
    5. Число "2": список аргументов [ -15, 2 ]
    6. Бинарный минус: берем -15 и 2 из списка, применяем оператор, кладём результат назад. Список аргументов [ -17 ]
    Токены закончились, в списке одно число -17. Это ответ.
    Ответ написан
    Комментировать
  • Почему при использовании with open не добавляются в сравнение отрицательные числа?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых, почему вначале read(1)? Это читает один символ, а не одну строку, так что если у тебя более 10 чисел в файле, работать будет некорректно.
    Во-вторых, isdigit() проверяет, что строка содержит только цифры. Знак "-" цифрой не является. Поэтому твой код такие строки игнорирует.
    Ответ написан
    3 комментария
  • Как сделать такой перебор через itertools на Python?

    Vindicar
    @Vindicar
    RTFM!
    Никак. Я бы решил по-другому.
    Рассматривай твою строку как число в N-рной системе счисления.
    Например, если среди символов строки могут быть только цифры 0-9 - это будут десятичные числа.
    Если будут a-z - то получим систему счисления с основанием 26.

    Тогда каждой строке можно будет соспоставить число - номер этой строки в списке всех возможных строк. В твоём случае "1111111111" соотвествует номер 0, "1111111112" - номер 1, и так далее.

    Соответственно, перебор строк будет сводиться к перебору всех чисел от 0 до числа возможных строк, с последующим переводом в выбранную "систему счисления". А остановка и возобновление перебора - сведётся к запоминанию текущего числа и выбору другой начальной позиции в следующий раз.

    Хотя можно и попытаться пропустить N первых строк в выхлопе product(), но это будет медленно, если нужно начать где-то в конце.
    Ответ написан
    Комментировать
  • Как получить другой элемент Literal?

    Vindicar
    @Vindicar
    RTFM!
    Литерал означает, что данная переменная/параметр всегда имеет одно из перечисленных значений. Так что...
    other_player_mark = 'cross' if mark == 'zero' else 'zero'

    Не, ты, конечно можешь извратиться...
    import typing as t
    
    Mark = t.Literal['cross', 'zero']
    
    class TicTacToePlayer:
        def __init__(self,
                     mark: Mark,
                     field: TicTacToeField
                     ):
            self.cells = []
            self.mark = mark
            self.field = field
        
        def opposite(self, mark: Mark) -> Mark:
            values = t.get_args(Mark)
            idx = values.index(mark)
            next_idx = int(not idx)
            return t.cast(Mark, values[next_idx])

    но лучше не надо!
    Ответ написан
  • Как разбить файл на несколько по буквам?

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

    Vindicar
    @Vindicar
    RTFM!
    recieved = await reader.read(2048)
    Ты читаешь 2КБ. И всё.
    Проблема в том, что размер пакета при передаче по сети ограничен. Хоть гигабайт отправь, приходить будет порциями. И вообще, отправитель (или промежуточное сетевое оборудование) может данные хоть по байту нарезать, ты это не контролируешь.
    Поэтому обязательно надо предусматривать какой-то способ определить конце передачи, и повторять чтение в цикле, поке конец не достигнут. Основных способов два.
    1. Передавать сначала размер данных в байтах (фиксированным размером - например, как 4байтовое целое), потом сами данные. Читаешь размер, разбираешь его в целое число, читаешь данные, пока не накопится желаемое число байт.
    2. После переданных данных передавать условную последовательность "конец передачи". Тогда читаешь данные, пока эта последовательность не встретится.
    У тебя данные бинарные, первый способ сработает лучше.
    Ответ написан