• Почему callback_query_handler не видит call.data?

    Vindicar
    @Vindicar
    RTFM!
    Во всех примерах это работает именно так...

    Не верю.

    bot.register_next_step_handler() принимает обработчик следующего сообщения, а не кнопки. Собственно, твоя функция и получает объект сообщения.
    Ответ написан
    2 комментария
  • Не правильная проверка ячейки таблицы через цикл, почему не записывается переменная?

    Vindicar
    @Vindicar
    RTFM!
    Ты уверен? Как насчёт явно задать порядок выборки нужных тебе столбцов в select?
    Что-то в духе SELECT id, name, chat_id FROM users. Названия столбцов укажи свои, и только используемые в данном коде.

    Далее, с БД так не работают. Ты выбираешь все строки, а потом вручную ищешь совпадение - это глупо.
    Лучше попроси БД найти нужные тебе строки.
    cur.execute('SELECT id, name FROM users WHERE chat_id = ?', (call.message.chat.id,))


    К слову, что ты подразумеваешь с под "третья"? Индекс 3? Или "третья с начала" (индекс 2)?
    Ответ написан
    Комментировать
  • Почему падает бот?

    Vindicar
    @Vindicar
    RTFM!
    Рвётся коннект до телеграмма. Сеть - штука ненадёжная, может у провайдера админ пьяный, может, контакт плохой, может, РКН балуется.
    Допиши скрипт, чтобы при ошибке соединения бот перезапускался.
    Я бы начал с чего-то типа
    import time
    from requests.exceptions import RequestException
    
    while True:
        try:
            bot.infinity_polling(timeout=10, long_polling_timeout = 5))
        except RequestException as err:
            print(err)
            print('* Connection failed, waiting to reconnect...')
            time.sleep(15)
            print('* Reconnecting.')
    Ответ написан
    1 комментарий
  • Как правильно использовать оператор or в pyautogui?

    Vindicar
    @Vindicar
    RTFM!
    Первый вариант правильный, второй не очень.
    Но есть два но:
    1. Тебе важен только сам факт наличия картинки на экране, или нужны её координаты?
    Если нужны координаты, то лучше сделать по умному, и не искать одну и ту же картинку дважды:
    # перечисляешь в списке изображения. цикл остановится на первом найденном.
    for image in ['link.png', 'link1.png']:
        location = pyautogui.locateOnScreen(image)
        if location is not None:
            break
    else:
        image, location = None, None

    Тогда дальше сможешь проверить, если location is not None - значит, что-то нашли. Что именно - лежит в image. Где именно - лежит в location.

    2. Какая у тебя версия библиотеки pyautogui? Начиная с 0.9.41, вместо функция locateOnScreen(), не найдя изображение, не вернёт None, а выкинет исключение. Тогда код будет выглядеть как-то так:

    for image in ['link.png', 'link1.png']:
        try:
            location = pyautogui.locateOnScreen(image)
        except pyautogui.ImageNotFoundException:
            pass
        else:
            break
    else:
        image, location = None, None
    Ответ написан
    Комментировать
  • Возникает ошибка, но не знаю какая?

    Vindicar
    @Vindicar
    RTFM!
    Волшебный человечек пришел в магазин и обнаружил, что у него есть ровно по две монетки каждого достоинства.

    Я не вижу, как ты учитываешь этот факт. Если ты прочитал со входа номиналы монет "5 10 50 100", то тебе нужно использовать для разложения список монет [5, 5, 10, 10, 50, 50, 100, 100].
    Ответ написан
  • Как это решать?

    Vindicar
    @Vindicar
    RTFM!
    1. Подумать.
    2. Написать код.

    А если серьёзно, задача сводится к разложению числа на заданные слагаемые. Это гуглится.
    Один из способов (необязательно самый быстрый) - рекурсивное разложение. Упрощенно, перебираешь все Ai меньшие N. Выкидываешь это Ai из рассматриваемого набора, и затем рекурсивно пытаешься составить число (N - Ai) из всех Aj, меньших или равных Ai (так как большие слагаемые ты уже рассмотрел).
    Углубляясь в рекурсию, рано или поздно ты наткнёшься на одну из двух ситуаций:
    а) среди Aj есть число, равное искомому. Решение найдено, осталось размотать рекурсию обратно и собрать в кучку использованные Ai.
    б) нет ни одного Aj, меньшего или равного искомому числу. Решения нет.
    В твоём случае будет ещё случай в) Сумма всех Ai меньше N. Решения нет, заплатить не удастся. Это можно проверить вообще сразу.

    Реализовать будет проще, если отсортируешь Ai в порядке убывания. Тогда вместо удаления Ai из списка слагаемых достаточно будет выбрать индекс i, с которого будешь начинать рассмотрение слагаемых - все элементы до i-го либо слишком велики, либо уже были рассмотрены и не пригодились.
    Ответ написан
    3 комментария
  • Как замокать метод __next__?

    Vindicar
    @Vindicar
    RTFM!
    Вообще делать return self из __iter__() не очень хорошая идея.
    Или верни итератор по внутренней коллекции, т.е. iter(self.nums). Это имеет смысл, так как чтение коллекции циклом for по-хорошему не должно приводить к её модификации. Для этого лучше сделать явный метод.
    Или сделай из __iter__() генератор, и делай yield значения.

    В обоих случаях определять __next__() не потребуется.
    Ответ написан
    2 комментария
  • Проверка редких кейсов в логике игр?

    Vindicar
    @Vindicar
    RTFM!
    ИМХО достаточно прописать у класса блока метод/обработчик события, который вызывается перед попыткой поставить блок по координатам и сообщает, можно ли его поставить. По дефолту метод может либо проверять базовые вещи типа "есть ли уже блок в этом месте", либо (если эта проверка вынесена за рамки метода и выполняется отдельно) тупо возвращать true.

    Это паттерн Полиморфизм, он встречается в наборе G.R.A.S.P. и ещё много где. Если на пальцах - если нужны разные реализации какой-то операции над разными типами объектов, нужно вместо большого дерева if-else-if-else-if-else сделать перегружаемый метод. Тогда можно будет возложить выбор правильной реализации метода на компилятор - к какому классу объект принадлежит, такой вариант метода и вызовется.
    Ответ написан
    Комментировать
  • Python Requests авторизация на сайте, как получить значения которые генирируются js?

    Vindicar
    @Vindicar
    RTFM!
    Вариант 1. Разобрать алгоритм, по которому генерируется значение-ключ, и воссоздать его в питоне.
    Вариант 2. Использовать эмулятор браузера, который может выполнять JS, типа selenium. Тоже не идеально.
    Ответ написан
  • Как найти в файле тхт нужную строку и добавить к ней другую переменную?

    Vindicar
    @Vindicar
    RTFM!
    Открыть исходный файл (open()), и еще один временный файл.
    Потом в цикле читать строки (readline()) и бить их на части по пробелу (str.split()).
    Если первая часть строки не равна s, то записываем строку во второй файл как есть.
    Если первая часть строки равна s, то изменяешь части строки как тебе требуется, формируешь новую строку и записываешь во второй файл.
    Когда пройдёшь по всем строкам файла, закрой оба файла, и используй os.replace(), чтобы заменить первый (исходный) файл вторым (изменённым).

    Готовый код не проси, за этим на фриланс.
    Ответ написан
    3 комментария
  • Как мне выполнить sql запрос?

    Vindicar
    @Vindicar
    RTFM!
    У тебя криво спроектированы таблицы. Реши для начала, кто ведущий, а кто ведомый в отношении Post-Money.
    Ведомый хранит ссылку на своего ведущего, но не наоборот.
    Если у тебя и впрямь просто реализуется связь многие ко многим, то связная таблица должна хранить ссылки на связываемые, но не наоборот.
    Ответ написан
    Комментировать
  • Как можно управлять ЦАПом MCP4725 при помощи python?

    Vindicar
    @Vindicar
    RTFM!
    Навскидку: написать прошивку под Ардуино, которая будет преобразовывать команды, полученные с Serial интерфейса, в манипуляции ЦАП-ом. После этого в питон-скрипте используешь пакет pyserial, чтобы работать с Ардуино через виртуальный COM-порт, и отдавать команды написанной тобой прошивке.

    Кроме того, есть такая штука как MicroPython, которая позволяет использовать (очень) ограниченный вариант Питона для написания прошивок непосредственно.

    Я фз что тебе больше подойдёт, так как не знаю, какую задачу ты решаешь.
    Ответ написан
    Комментировать
  • Как передать параметр в декоратор в рантайме?

    Vindicar
    @Vindicar
    RTFM!
    Декорировать функцию после получения параметров. Не забывай, что
    @formatter(p1, p2)
    def csv_reader(filename, request):
        ...

    эквивалентно
    def csv_reader(filename, request):
        ...
    
    _temp = formatter(p1, p2)
    csv_reader = _temp(csv_reader)


    Альтернативно, пусть возвращаемая фукнкция имеет свойства:
    def formatter(parse_func):
        def output_func(*args):
            ...  # тут обращаемся к output_func.p1, например
    
        output_func.p1 = p1
        output_func.p2 = p2
        return output_func
    
    
    @formatter
    def csv_reader(filename, request):
        ...
    
    csv_reader.p1 = a1
    csv_reader.p2 = a2

    Вместо функции можно вообще вернуть callable object, т.е. объект класса с методом __call__(), и любыми нужными свойствами и методами.
    Ответ написан
    1 комментарий
  • Почему метод get.users, flieds = online, возвращает None?

    Vindicar
    @Vindicar
    RTFM!
    Попробуй передать параметр по имени, .get(user_ids=user_id)
    Ответ написан
  • Почему код перестает работать при импорте?

    Vindicar
    @Vindicar
    RTFM!
    sqlite не поддерживает толком одновременную работу в нескольких потоках.

    1. У тебя парсер? Перепиши код на асинхронный, тебе не сдалось на самом деле использовать потоки. Они 90% времени будут спать и ждать сетевого ответа. Асинхронный код выполняется в одном потоке, так что таких проблем не будет.
    2. Создай отдельный поток, который будет заниматься только работой с базой, и общаться с остальными через какое-то api, например, кладём запрос, данные и какой-то id в очередь, потом читаем ответ из словаря. Но ты по факту будешь писать свой кривенький СУБД-сервер, так что...
    3. Вместо sqlite используй любую полноценную СУБД, которая умеет параллельные соединения. Postrge, mariadb, что угодно.
    Ответ написан
  • Как изменить вывод данных из промиса?

    Vindicar
    @Vindicar
    RTFM!
    data.forEach(function(rowData.name)
    Намекает, что стоит подучить язык, это вообще некорректный синтаксис.
    Начало у тебя правильное:
    data.forEach(function(rowData) { ... }
    в rowData будут попадать элементы массив data, т.е. { name: 'John', age: 25 }
    Тогда в теле (в теле! не в заголовке!) своей анонимной функции можешь обращаться к rowData.name.
    Скажем,
    data.forEach(function(rowData) { console.log(rowData.name); } );

    А вообще я бы не использовал forEach(), а использовал бы простой цикл for.
    for (let i = 0; i < data.length; i++)
    {
        console.log(data[i].name);
    }
    Ответ написан
  • Отличается ли мультипроцессинг от запуска нескольких программ?

    Vindicar
    @Vindicar
    RTFM!
    Простотой коммуникации между скриптами, в т.ч. распределения задач между ними.

    Во-втором случае у тебя есть готовое решение по распределению задач и сборке результатов. Но с ограничениями - например, под капотом используется pickle, так что передавать можно только ограниченный набор объектов.

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

    Vindicar
    @Vindicar
    RTFM!
    Вместо строки возвращай кортеж или словарь. Короче, структуру данных.
    from typing import NamedTuple
    
    class Result(NamedTuple):
        text: str  # текст запроса
        success: bool  # успешен ли запрос
        status: str  # статус
    
    async def check_text(text: str) -> Result:
        url = f'https://сайт.com/?query={text}'
    
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                if response.status != 200:
                    return Result(text=text, success=False, status='Не удалось определить результат')
                html = await response.text()
                soup = BeautifulSoup(html, 'html.parser')
                status_element = soup.find('div', class_='table-block')
                if not status_element:
                    return Result(text=text, success=False, status='Не удалось определить результат')
                status_text = status_element.get_text().strip()
                # тебе нужно будет решить, когда запрос был успешен (True), а когда нет (False)
                if "ok" in status_text:
                    return Result(text=text, success=True, status='Можно')
                elif "no" in status_text:
                    return Result(text=text, success=False, status='Данный вариант недоступен')
                elif "no1" in status_text:
                    return Result(text=text, success=True, status='Можно под заказ')
                else:
                    return Result(text=text, success=False, status='Неизвестно')

    Тогда можно будет анализировать результат просто:
    result = await check_text(text)
    if result.success:
        ...  # реагируем на успешный запрос
        logger.info('%s: %s', result.text, result.status)
    else:
        ...  # реагируем на неудачный запрос
        logger.info('%s: %s', result.text, result.status)
    Ответ написан
  • Не могу исправить проблему, бот не может отправить сообщение по нажатии кнопки?

    Vindicar
    @Vindicar
    RTFM!
    Ну твоя проблема уже тут:
    @bot.callback_query_handler(func=lambda call: True)

    Ты говоришь боту "вызывай эту функцию всякий раз, когда пользователь нажимает кнопку"(callback_query_handler), и добавляешь "неважно, какая кнопка была нажата" (func=lambda call: True).
    Поэтому у тебя callback() будет вызываться при нажатии ЛЮБОЙ кнопки.

    Если ты хочешь, чтобы при нажатии разных кнопок вызывались разные функции, тебе нужно разделить их с помощью параметра func. В нём ты передаёшь маленькую функцию-фильтр, которая отвечает на вопрос "может ли эта функция обработать это нажатие?". Бот перебирает зарегистрированные callback-обработчики, и вызывает первый, чей фильтр вернул True.

    Т.е. тебе нужно написать такие фильтры, которые смогут разделить нажатия отдельных кнопок.
    Простой способ это сделать - реализовать иерархию в callback_data, например так:
    # обрабатываем то, что начинается с 'city.'
    @bot.callback_query_handler(func=lambda call: call.data.startswith('city.'))
    def callback(call):
        city = call.data[len('city.'):]  # отрезаем префикс 'city.'
        if city == 'istanbul':
            bot.send_message(call.message.chat.id,'Вы выбрали город: Стамбул')
        elif city == 'moscow':
            bot.send_message(call.message.chat.id,'Вы выбрали город: Москва')
        else:
            bot.send_message(call.message.chat.id,'Я не знаю такого города')

    А до этого ты где-то в другом обработчике послал сообщение с клавиватурой вида
    keyboard = types.InlineKeyboardMarkup()
    # обрати внимание, callback_data всегда начинается с 'city.'
    keyboard.add(types.InlineKeyboardButton('Стамбул', callback_data='city.istanbul'))  
    keyboard.add(types.InlineKeyboardButton('Москва', callback_data='city.moscow'))

    Так ты можешь разделить обработчики для разных наборов кнопок.

    Еще советую почитать про FSM.
    Ответ написан