Задать вопрос
  • Как сделать свять вежду python игрой и сайтом на html?

    Vindicar
    @Vindicar
    RTFM!
    1. Ты должен выбрать себе схему URL, по аналогии с тем, как это делает телеграм с его схемой tg:// или стим (steam://).
    2. Научись упаковывать свою игру в exe-файл с помощью любого упаковщика - например, auto-py-to-exe.
    3. Подразумевается, что игра уже установлена на компьютере пользователя. При установке она регистрирует себя как обработчик для данной схемы. Это делается по-разному для винды и для линукса.
    Для винды нужно будет залезть в реестр через стандартный модуль registry

    Тебе нужно создать ключ реестра HKEY_CLASSES_ROOT/ИмяТвоейСхемы. Убедись, что такого ключа нет, перед тем как его создавать!
    В ключе создаёшь строковое значение с именем URL Protocol и пустым значением.
    Создаёшь вложенный ключ: HKEY_CLASSES_ROOT/ИмяТвоейСхемы/shell
    Внутри вложенного ключа создаёшь строковое значение с именем command и значением такого вида: "C:\путь\к\твоей\игре.exe" "%1"

    После этого при попытке ввести в браузере ссылку, начинающуюся с твоей схемы, должна запуститься твоя игра.
    3. Твоя игра должна проверять параметры командной строки (читай про sys.argv). Если игра запущена без параметров - её запустили просто ярлыком. Если игра запущена с одним параметром, и он начинается с твоей схемы - её запустил клик по ссылке. Разбирай текст ссылки в параметре и решай, что игра должна сделать.

    Технически, ты не обязан сам лезть в реестр в python-скрипте - ты можешь сделать это ручками через regedit или поручить это установщику, типа NullSoft. Он же позаботится о том, чтобы снести созданные ключи при удалении игры.
    Я бы сначала попробовал зарегистрировать URL вручную, убедился что это работает, а потом уже игрался бы с установщиком.
    Ответ написан
    Комментировать
  • SyntaxError: 'await' outside function. Как исправить ошибку кода, который должен пересылать удаленные сообщения в телеграмме в избранное?

    Vindicar
    @Vindicar
    RTFM!
    await client.run_until_disconnected()
    Эта строка где находится? Вне функции? А почему?
    Выглядит как будто ей место в main().
    Ответ написан
    Комментировать
  • Как обойти ошибку Tcl_AsyncDelete: async handler deleted by the wrong thread?

    Vindicar
    @Vindicar
    RTFM!
    Поясню ответ выше: насколько я знаю, графические интерфейсы строго однопоточны. Как минимум под Windows это так, а потому ни один графический фреймворк не поддерживает обращение к окнам и их элементам из других потоков.
    Как следствие, если ты хочешь организовать фоновый поток с "обратной связью" в GUI, обычно требуется использовать очередь, например, queue.Queue. В эту очередь фоновый поток должен класть сообщения, объясняющие, что надо сделать - например, сведения о прогрессе операции, или команды на смену состояния, или ещё что. Это зависит от твоей задачи.
    Тогда основной поток программы, который и отвечает за GUI, должен использовать средства фреймворка для периодической проверки очереди на предмет сообщений. Например, в обычном tkinter это будет реализовано через метод after().
    Если в очереди есть сообщения, основной поток читает их и выполняет соответствующие действия - например, меняет положение прогресс-бара, включает/выключает кнопки, и т.д.
    Если фоновый (рабочий) поток живёт долго, то может иметь смысл организовать вторую очередь для передачи команд из GUI-потока в рабочий. Идея та же самая: рабочий поток ждёт появления команды в своей входной очереди, и выполняет её, а потом сбрасывает уведомления в исходящую очередь.
    Ответ написан
    Комментировать
  • Как вывести роли discord сервера, кроме заблокированных?

    Vindicar
    @Vindicar
    RTFM!
    В discord.py ты можешь просто сравнивать роли. Но ты пытаешься сделать это вручную...
    Если заглянуть в исходники либы, то можно увидеть, что там проверяется свойство position. Причем вроде как меньший position означает меньшие привилегии, с поправкой на то что роль @everyone меньше всех.
    Тогда решением твоей задачи будет:
    1. Определить список ролей твоего токена на рассматриваемом сервере.
    2. Определить наибольший position среди этих ролей.
    3. Получить список всех ролей на рассматриваемом сервере.
    4. Отсеять роли, у которых position больше твоего наибольшего.

    Если я напутал и меньший position означает большую роль, то логика примерно та же самое, только меняешь больше на меньше.
    Ответ написан
  • Как добавить фон скрипту, запускаемому через консоль?

    Vindicar
    @Vindicar
    RTFM!
    Полноценную картинку в консоли не покажешь, тут тебе не линукс. Но ASCII-арт можно - вопрос только как разделить вывод текста игры и вывод ascii-арта. Например, сделать два логических "окна" в одном терминале.

    Ставишь пакет windows-curses, после этого можно будет и на винде использовать стандартный модуль curses. Он и это умеет, и цветной вывод.
    Ответ написан
    Комментировать
  • Как добавить несколько изображений к locateOnScreen?

    Vindicar
    @Vindicar
    RTFM!
    Никак, функция ищёт одно изображение.
    Если тебе нужно несколько, ищи их последовательно, пока не найдётся хотя бы одно из них.
    Ответ написан
    2 комментария
  • Как можно в Linux настроить маршрутизацию для доменов 1-ого уровня?

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

    Vindicar
    @Vindicar
    RTFM!
    Ignis138, ты основы питона почитай немножечко, чтобы хоть понимать, где у тебя в коде что.
    Ты в тексте запроса указал, что у тебя в запросе есть подставляемое значение по имени degress_id. Это имя никак не обязанно коррелировать с именем переменных, sqlalchemy ничего не знает о твоих переменных. Так что теперь ты должен указать, какое значение должно быть подставлено.
    with Session(self.engine) as s:
        query = """
            SELECT direction, profile,budget,commerce,min
            FROM directions
            WHERE d_id = %(degress_id)s
            """
        rows = s.execute(text(query))  # вот где-то тут

    Заглядываем в документацию (окей, гугл, sqlalchemy Session execute).
    Быстренько находим ссылку на описание самого класса Session (в противоположность общим объяснениям как им пользоваться).
    Ищем описание метода execute().
    Читаем список параметров:

    statement – An executable statement (i.e. an Executable expression such as select()).

    Иными словами, запрос, который надо выполнить. Ты его передаёшь как text(query).

    params – Optional dictionary, or list of dictionaries, containing bound parameter values. If a single dictionary, single-row execution occurs; if a list of dictionaries, an “executemany” will be invoked. The keys in each dictionary must correspond to parameter names present in the statement.

    Словарь или список словарей. У тебя один запрос, так что нужен один словарь. Ключи словаря должны соответствовать именам параметров. У тебя в запросе указан один параметр degress_id.

    Таким образом, приходим к тому, что вторым параметром нужно передать словарь, в котором есть один ключ "degress_id" и сопоставленное ему значение.

    И вот тут мы снова подходим к началу поста: если б ты озаботился почитать про основы языка, в частности, что такое словари (окей, гугл, python словарь).
    Тогда, глядишь, дошёл бы и до такой конструкции:
    degress_id_value = ...  # тут ты определяешь, какое значение подставляешь в запрос
    rows = s.execute(text(query), {"degress_id": degress_id_value})
    Ответ написан
    Комментировать
  • Стоит ли использовать ООП для бота на Telebot?

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

    Vindicar
    @Vindicar
    RTFM!
    3FANG,
    насчёт твоего второго вопроса: всё предельно просто. Ты запустил 10 копий корутины, они все выполнили print('start') и ушли в спячку на две секунды - практически одновременно!
    Точнее, первая корутина встала в очередь, create_task() закончила свою работу и вернула управление в твой цикл запуска корутин. И так 10 раз. Все корутины стоят в очереди плотно друг за другом.
    Затем ты входишь в цикл ожидания корутин, пишешь в консоль "старт", дожидаешься первой корутины, при этом main() встаёт в очередь на вызов. Первая корутина запустилась, написала start, и ушла в ожидание. Следующая в очереди готова вторая корутина. Она запустилась, написала start, ушла в ожидание. И так далее. В конце main() снова оказывается в начале очереди - но она ждёт первую корутину, она ещё не готова выполняться. Она отправляется в конец очереди. Поэтому программа ждёт первую корутину, но ожидание-то тикает у всех!
    Тогда первая корутина отработала - но прежде чем ты вернёшься из await-вызова в main(), сначала успеют отработать всё стоящие в очереди корутины, потому что их время тоже подошло, и они стоят в очереди раньше! И ты видишь последовательность start-finish внутри корутин.
    Затем очередь вызова доходит до main() и ты видишь "финиш" ожидания первой корутины. Ты начинаешь ждать вторую (старт) - но она уже отработала, поэтому main() единственная в очереди, и она тут же получает управление обратно (финиш). И так с оставшимися корутинами.

    Если ты сделаешь так, чтобы каждая следующая копия корутины ждала дольше предыдущей, то ситуация будет интереснее:
    код
    import asyncio 
    from time import time, sleep
    
    
    async def waste_time(i, delay):
        print(f"Start work {i}...")
        await asyncio.sleep(delay)
        print(f"End work {i}!")
    
    
    async def main():
        tasks = []
    
        for i in range(10):
            task = asyncio.create_task(waste_time(i+1, (i+1)*1.0))
            tasks.append(task)
    
        for i, task in enumerate(tasks, 1):
            print(f'start wait {i}')
            await task
            print(f'end wait{i}')
    
    if __name__ == '__main__':
        start = time()
        asyncio.run(main())
        print(time() - start)

    вывод
    start wait 1
    Start work 1...
    Start work 2...
    Start work 3...
    Start work 4...
    Start work 5...
    Start work 6...
    Start work 7...
    Start work 8...
    Start work 9...
    Start work 10...
    End work 1!
    end wait1
    start wait 2
    End work 2!
    end wait2
    start wait 3
    End work 3!
    end wait3
    start wait 4
    End work 4!
    end wait4
    start wait 5
    End work 5!
    end wait5
    start wait 6
    End work 6!
    end wait6
    start wait 7
    End work 7!
    end wait7
    start wait 8
    End work 8!
    end wait8
    start wait 9
    End work 9!
    end wait9
    start wait 10
    End work 10!
    end wait10
    10.012470483779907
    Ответ написан
    5 комментариев
  • Как решить disnake.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'str' object has no attribute 'timeout'?

    Vindicar
    @Vindicar
    RTFM!
    Включаем логику.
    Ты хочешь, чтобы бот сделал вот это:
    await member.timeout(reason=reason, until=duration)  # timeout() - метод класса discord.Member

    Но! У тебя заголовок функции-обработчика описан так:
    async def mute(self, inter, member, duration = "Навсегда", reason: str = "Не указана"):

    Ты не указал тип member - по умолчанию это будет строка. Если тебе нужно, чтобы тут была ссылка на участника сервера, ты должен был указать соответствующий тип, как это показано в документации на библиотеку. Для discord.py ссылка тут, в disnake это должно делаться похожим образом, так как диснейк базируется на дискорд пи. В любом случае, если что-то непонятно - сначала находишь и читаешь документацию и примеры в ней.

    В твоём случае этого примера должно быть достаточно, чтобы понять, что нужно изменить в заголовке mute().
    Ответ написан
    Комментировать
  • Имитация веб-камеры - как автоматизировать на python (linux)?

    Vindicar
    @Vindicar
    RTFM!
    Извини, а у тебя ничего не ёкнуло вот тут?
    sudo apt install v4l2loopback
    pip install v4l2loopback
    Ты понимаешь разницу между этими двумя командами?
    Первая - задействует системный менеджер пакетов для дистрибутивов на базе debian (deb-пакетов).
    Вторая - задействует встроенный менеджер пакетов питона.
    Это совершенно разные вещи, и они работают с совершенно разными репозиториями.
    Установить deb-пакет в систему, на которой будешь тестить, достаточно будет один раз.
    Прописать мод можно в /etc/modules, но можно и тупо делать modprobe при загрузке системы.
    И то и то, я полагаю, можно сделать хоть на живой системе, хоть внутри докера.

    После этого в автотесте запускаешь ffmpeg, можно даже тупо через subprocess вместо питоновских модулей. Сюрприз, сюрприз! Они все, насколько я знаю, именно так и делают под капотом. Я не видел модуля, который бы имел интегрированный ffmpeg.
    Ответ написан
    3 комментария
  • Ошибка TypeError: work_command() missing 1 required positional argument: 'points' что делать?

    Vindicar
    @Vindicar
    RTFM!
    @bot.message_handler(content_types=['text'])
    def work_command(message, points):


    Бот ничего не знает про points и откуда оно берётся. Бот ожидает, что любая функция, отмеченная как обработчик сообщений, принимает ровно один параметр - объект принятого сообщения. Если это условие не выполняется, это твой косяк.

    если делать global points то будет у всех один баланс

    Вовсе нет. Ты не обратил внимание, что у тебя points - словарь, где ключ - id пользователя? (к слову, кто код писал? уж точно не разраб-крут). У тебя для разных id пользователей будут отдельные элементы в словаре, с отдельными значениями.

    Другое дело, что словарь не переживёт перезапуска бота...
    Ответ написан
  • Как сделать бота поддержки с при помощи библиотеки telebot?

    Vindicar
    @Vindicar
    RTFM!
    Не пытайся объявлять обработчики событий динамически, внутри других обработчиков. Это не будет работать так, как ты это ожидаешь!
    А для начала определись с ответом на вопрос: если есть несколько одновременных обращений, то как бот поймёт, кому отвечает оператор?

    Один из вариантов

    Оператор должен явно отвечать (через соотв. пункт меню) на сообщение бота.
    Тогда бот должен хранить список вида "id сообщения в группе, id пользователя. Можешь хранить в БД или ином хранилище (БД в конечном итоге будет проще всего).

    В этом случае логика бота по обработке сообщения будет такая:
    1. Если сообщение в личке: отправить копию сообщения в группу, сохранить в БД id пользователя и id отправленного ботом сообщения.
    2. Если сообщение в группе, и это ответ: поискать в БД id сообщения, на которое ответ. Если id найдено - извлечь соответствующее id пользователя, отправить ему копию сообщения.
    3. Если id не найдено: что должен сделать бот?
    4. Если сообщение в группе, но это не ответ: что должен сделать бот?

    Можно также прикреплять к записи в БД дату, чтобы время от времени можно было выкидывать из БД старые сообщения. Это уже упражнение для читателя.
    Ответ написан
    Комментировать
  • Какую библитеку или интерфейс выбрать?

    Vindicar
    @Vindicar
    RTFM!
    Насчёт фреймворка не подскажу, а подскажу вот что: не нужно пытаться запихнуть всю безразмерную таблицу в GUI. Прокрутка - определение позиции - выборка данных, видимых на экране - рендеринг. Как-то так.
    Ответ написан
    2 комментария
  • Написал код на pycharm с изображениями, но он не работает. Не понимаю что не так. В чём ошибка?

    Vindicar
    @Vindicar
    RTFM!
    Ты указал относительный путь к файлу picture.png.
    Поскольку путь относительный (т.е. не начинается от корня диска), программа ищёт его относительно текущей рабочей директории. Эта директория может различаться по обстоятельствам, но в твоём случае итоговый путь оказывается таким: C:\\Users\\Уваж Руслан Рафэкови\\PycharmProjects\\pythonProject\\Tests\\picture.png
    У тебя точно по этому пути лежит корректный файл изображения? Потому что судя по тексту ошибки, его там нет.
    Ответ написан
    Комментировать
  • Возможно ли создать универсальное решение для процесса синхронизации данных от разных поставщиков?

    Vindicar
    @Vindicar
    RTFM!
    Разные форматы/особенности данных - разные обработчики.
    Максимум, можешь использовать полиморфизм и оформить обработчики под каждого поставщика как классы с общим предком/интерфейсом и использовать паттерн "Цепочка ответственности".
    Ответ написан
  • Бот отправляет 2 раза сообщение, которое не нужно отправлять в данный момент + не хочет отправлять результаты в группу, Как решить эти 2 проблемы?

    Vindicar
    @Vindicar
    RTFM!
    return (test_g, test_k)
    bot.send_message(айди группы, f'@{message.from_user.username} / {message.from_user.id} отправил тест на проверку\nЕго варианты были\nhttps://forms.gle/{test(message)[0]}\nhttps://forms.gle/{test(message)[1]}')


    Полнейшая чушь.

    Во-первых, запомни, что обработчики событий (всё, что декорировано message_handler() или подобным) не следует вызывать самостоятельно. Вот просто не следует. Их вызывает бот по мере надобности. Как следствие, возвращать из них тоже ничего не следует - бот это проигнорирует, а ты эти значения не получишь.

    Во-вторых, выучи концепцию побочных эффектов при вызове функции и держи её в голове. Ты на ровном месте делаешь два вызова test(), которая имеет побочные эффекты в виде отправки сообщения, а потом удивляешься, что два раза отправляются сообщения! Причем именно что на ровном месте. Вот тебе что, грозят болтающееся отрезать за сохранение результата test() в ещё одну локальную переменную перед использованием этого результа? Конечно, это непринципиально, потому что test() вызывать нельзя (см. пункт 1), но всё равно показательно.

    А что касается передачи инфы о действиях пользователя - заведи хранилище вида "id пользователя - пара ссылок". Подойдёт даже словарь, если тебе не нужно, чтобы инфа переживала перезапуск бота. И вот оттуда уже в well() вытаскивай инфу о том, что проходил текущий пользователь.

    Учись программировать, потом пиши ботов. Не наоборот.
    Ответ написан
    Комментировать
  • Как при создании телеграмм бота сложить несколько переменных?

    Vindicar
    @Vindicar
    RTFM!
    Это потому что текст сообщения пользователя - строка. Для строк, "1" + "1" = "11", потому что сложение строк - это конкатенация.
    Преобразуй строки в числа. Для целых это просто
    s = "11"
    x = int(s)  # x = 11

    Для дробных чисел сложнее. Конечно, можно сделать по аналогии:
    s = "1.1"
    x = float(s)  # x = 1.1

    Но тут требуется десятичная точка, т.е. "1,1" не прокатит. Отчасти это можно компенсировать заменой, например,
    s = "1,1"
    x = float(s.replace(",", "."))  # x = 1.1

    Коряво, но сработает.
    Ответ написан
    Комментировать
  • Хочу написать python Бота который играет в сапер за меня, и наверное мне нужно наставление более опытного?

    Vindicar
    @Vindicar
    RTFM!
    1. Ввод данных
    Окей, гугл, как сделать скриншот в питоне

    2. Предобработка данных
    Используя что-то типа opencv matchTemplate(), превращаешь скриншот в двухмерный массив, описывающий игровое поле.

    3. Принятие решения
    Имея двухмерный массив, описывающий поле, определи, где надо ставить мину. Если решение принять не удаётся - определи, какую клетку надо открывать.

    4. Реализация решения
    Зная номер клетки, выполнить щелчок по ней. См. pyautogui.
    Ответ написан
    Комментировать