• Выводит ошибку, как можно исправить? (Error code: 400. Description: Bad Request: chat not found)?

    Vindicar
    @Vindicar
    RTFM!
    Как читать трейсбэк? Он состоит из записей вида:
    v                         в каком файле ошибка                           v   v строка v    v     функция    v
    File "/home/maksim/.local/lib/python3.10/site-packages/telebot/__init__.py", line 1074, in __threaded_polling
    self.worker_pool.raise_exceptions()
    ^   оператор, вызвавший ошибку    ^

    Смотрим записи по одной, сверу вниз, и ищем те, которые относятся к твоему коду. У тебя только одна такая запись:
    File "/home/maksim/Загрузки/Python/Квест/Квест.py", line 33, in questions
    bot.send_message(_id, 'Комфортно ли вам находиться в обществе?', reply_markup=markup)

    Почему именно эта? Потому что только в ней путь к файлу не ссылается на lib/python
    Значит, ошибка именно в строке
    bot.send_message(_id, 'Комфортно ли вам находиться в обществе?', reply_markup=markup)

    Текст ошибки звучит как chat not found. Т.е. не найден чат с таким идентификатором, который ту указал. А значит, в переменной _id содержится неправильное значение. Выясняй, как оно туда попало.
    Ответ написан
    Комментировать
  • Как можно исправить странную ошибку в коде python?

    Vindicar
    @Vindicar
    RTFM!
    description(400)
    это что?

    EDIT: а не, SQLite такое позволяет. У тебя ошибка в другом месте:
    category_id INTEGER NO NULL
    "NOT NULL", а не "NO NULL"
    Ответ написан
  • Как в Python можно изменить запись в CSV?

    Vindicar
    @Vindicar
    RTFM!
    Нет, по-простому нельзя. Единственный простой подход (который показал выше Максим Припадчев) - загрузить целиком в память, там изменить, потом выгрузить назад. Для больших CSV файлов это ресурсоёмко.

    CSV вообще не предназначен для долговременного хранения данных - скорее, для импорта/экспорта.

    Ты мог бы попытаться использовать методы tell() и seek(), чтобы "запомнить" позицию удаляемой строки, а затем в цикле копировать всё что идёт после, "пододвинув" содержимое внутри файла, а потом уже дописать в конец изменённую строку. Но это всё равно долго.

    Лучше импортируй файл в базу SQLite, и работай в дальнейшем уже с ней.
    Ответ написан
    3 комментария
  • Как произвольно трансформировать изображение в Python?

    Vindicar
    @Vindicar
    RTFM!
    Скажи спасибо, что я делал такую лабораторную работу X)
    Код
    # -*- coding: utf-8 -*-
    import sys
    import numpy  # pip install numpy
    import cv2  # pip install opencv-python
    
    def loadImg(fname : str) -> numpy.ndarray:  # грузит файл
        data = numpy.fromfile(fname, dtype=numpy.uint8)
        img = cv2.imdecode(data, cv2.IMREAD_COLOR)
        if img is None:
            raise IOError("Not an image file")
        return img
    
    class Clicker:  # класс для выбора точек на экране
        def __init__(self, name: str, image: numpy.ndarray):
            self.wnd = name
            self.image = image
            self.clicks = []
            self.markersize = 5
            self.markercolor = (255,0,255)
            cv2.namedWindow(self.wnd, cv2.WINDOW_AUTOSIZE)
            cv2.setMouseCallback(self.wnd, self._click)
        
        def draw(self):  # рисует точки на изображении и выводит их на экран
            copy = self.image.copy()
            color = self.markercolor
            radius = self.markersize
            for x,y in self.clicks:
                cv2.circle(copy, (x,y), radius, color, 1)
                cv2.line(copy, (x-radius,y), (x+radius,y), color, 1)
                cv2.line(copy, (x,y-radius), (x,y+radius), color, 1)
            cv2.imshow(self.wnd, copy)
        
        def _click(self, event, x, y, flags, param):
            if event == cv2.EVENT_LBUTTONDOWN:  # левый клик - поставить точку
                self.clicks.append((x,y))
            elif event == cv2.EVENT_RBUTTONDOWN:  # правый клик - сбросить последнюю точку
                if self.clicks:
                    del self.clicks[-1]
            else:
                return
            self.draw()
        
        def close(self):
            cv2.destroyWindow(self.wnd)
        
        def __enter__(self):
            self.draw()
            return self
        
        def __exit__(self, exctype, excvalue, traceback):
            self.close()
    
    try:
        image = loadImg('times-square.jpg')  # изображение, внутрь которого вписываем другое
        poster = loadImg('lena.png')  # изображение, которое вписываем в первое
    except IOError:
        print('Ошибка загрузки файла.')
        sys.exit(1)
    # эта часть только для ручного ввода координат
    # если они уже есть, то это не нужно.
    with Clicker('Select area', image) as clicker:
        # четыре точки ставятся строго по часовой, начиная слева-сверху 
        while len(clicker.clicks) < 4:  # пока не получили четыре точки - угла
            if cv2.waitKey(100) == 27:
                print('Отменено')
                sys.exit(0)
        pts = numpy.array(clicker.clicks, dtype=numpy.float32)  # координаты углов тут
    # вписываем изображение
    height, width = poster.shape[:2]
    srcpoints = numpy.array([  # углы вставляемого изображения в том же порядке по часовой
        (0,0),
        (width-1, 0),
        (width-1, height-1),
        (0, height-1),
    ], dtype=numpy.float32)
    # матрица преобразования сопоставляет четыре точки второго изображения с точками первого
    # по сути, она позволяет перейти от второго изображения к первому
    matrix = cv2.getPerspectiveTransform(srcpoints, pts)  # порядок аргументов важен, иначе переход будет наоборот
    # применяем матрицу ко второму изображению. Но теперь надо убрать чёрные поля.
    warped = cv2.warpPerspective(poster, matrix, (image.shape[1], image.shape[0]))
    # делаем маску для переноса пикселей с warped на image
    # мы хотим перенести только пиксели, на которые пришлись пиксели второго изображения
    mask = numpy.zeros(image.shape, dtype=numpy.uint8)  # рисовать можно только на обычном изображении
    # закрашиваем пиксели внутри выбранного ранее четырёхугольника
    cv2.fillPoly(mask, pts.reshape(1, -1, 2).astype(numpy.int32), (1,1,1))
    mask.dtype = bool  # а для переноса нам нужна логическая маска
    # маска готова, переносим. numpy рулит, правда ведь?
    image[mask] = warped[mask]
    # показываем результат
    cv2.imshow('Result', image)
    cv2.waitKey()


    Если коротко: находишь точки, которым надо сопоставить углы "вставыша". Перечисляешь их в том же порядке, что и эти углы. Находишь матрицу перспективного преобразования. Применяешь матрицу к вставышу, получаешь чёрное изображение, на котором вставыш расположен в нужном месте. Переносишь пиксели с этого изображения на картинку с экраном.
    Ответ написан
    3 комментария
  • При запуске элементарного кода(правильного) на vkbottle выдает огромное количество ошибок. Что делать?

    Vindicar
    @Vindicar
    RTFM!
    aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host api.vk.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1002)')]

    У тебя или провайдер сильно хитропопый, или вирусня на компе. Самоподписанных сертификатов в цепочке сертификатов для любого нормального сайта быть не должно и точка, а для контакта тем более. Так что кто-то пытается перехватить соединение. Кто - без понятия. Проверь на заведомо чистой машине и работая через VPN, также проверь список установленных корневых сертификатов, нет ли там чего странного. Как - написано в гугле.
    Ответ написан
  • Часто ли телеграм боты подвергаются атакам и как вы этого избегаете?

    Vindicar
    @Vindicar
    RTFM!
    Ну для начала что значит "атака"? Какую угрозу ты ожидаешь? Потому что ответы будут ОЧЕНЬ разные в зависимости от этого.

    IP бота можно будет попробовать узнать, если ты знаешь, что бот проходит по ссылкам, которые ты можешь ему отправить. Тогда, скинув боту ссылку на свой сайт, можно будет посмотреть, какие адреса заходили в этот момент.
    Если бот такого не делает, то скорее всего никак.

    Зафлудить бота запросами? С одного аккаунта не получится, а с многих - недёшево. Кому ты нужен за такие деньги?

    Потыкать команды бота на пример SQL-инъекции? Если бот вообще использует БД, достаточно использовать стандартные средства подстановки параметров в запросы, а не колхозить SQL чере зформатирование строк.

    Угнать бота? Не пости его токен никуда. Если хранишь исходный код в какой-то системе хранения версий - храни токен в отдельном файле и добавь его в исключения. Если есть подозрение, что токен уже уплыл - меняй его у BotFather. А угон акка разработчика - это другая песня уже.

    Короче, ответь хотя бы для себя на вопросы:
    1. чего конкретно боишься?
    2. кому конкретно ты нужен?
    Ответ написан
    2 комментария
  • Что делать если не загружается кога discord.py?

    Vindicar
    @Vindicar
    RTFM!
    for filename in os.listdir("./cogs"):
    Ты ищешь подкаталог cogs в текущем рабочем каталоге программы.
    Это не то же самое, что и каталог, где находится программа.
    Ты уверен, что у тебя путь к нужному каталогу?
    from pathlib import Path
    import sys
    # каталог скрипта
    SCRIPT_DIR = Path(sys.argv[0]).parent.resolve()
    # каталог с когами
    COGS_DIR = SCRIPT_DIR / 'cogs'
    # список имён когов
    COGS = [f.stem for f in COGS_DIR.glob('*.py')]
    Ответ написан
    Комментировать
  • Как верно настроить вероятность в мини - игре?

    Vindicar
    @Vindicar
    RTFM!
    0. Главное: вопрос у тебя звучит "Как верно настроить вероятность". В коде ровно одна строчка с random, и ты не объясняешь что она делает. Собственно, и правила игры (т.е. желаемое поведение кода) ты не озвучил. Что такое "подкрутка"? Что тут посоветуешь...
    1. Если ты ловишь себя на том, что создаёшь переменные вида mine_3, mine_4, mine_5, а дальше делаешь x = eval(f"mine_{mines_kolv}[{now_state}]") тебе нужна индексируемая коллекция! Список или кортеж. Тем более что списки ты уже используешь, значит, знаешь, что это такое. Неужели "список из списков" - это такая сложная концепция?
    2. У тебя в самом первом SQL-запросе подстановка параметров выполняется корректно, а дальше идёт ересь с использованием %-форматирования. Не надо так.
    3. У тебя куча таблиц, из которых ты вытаскиваешь по одному значению. Если эти значения всегда требуются вместе, почему не объединить их в одну таблицу?

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

    Vindicar
    @Vindicar
    RTFM!
    AudioSegment.converter = f"{os.getcwd()}\\ffmpeg.exe"

    Ты уверен, что файл лежит в текущем каталоге? Это не то же самое, что каталог программы.
    Если тебе нужен каталог программы, лучше его и взять:
    from pathlib import Path
    import sys 
    
    SCRIPT_DIR = Path(sys.argv[0]).parent.resolve()
    FFMPEG = SCRIPT_DIR / 'ffmpeg.exe'  # чтобы не париться с разделителем каталогов (/ или \)
    Ответ написан
    Комментировать
  • Метод insert не работает, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    Ну тут сразу возникает вопрос: какую задачу выполняет этот метод. Ты говоришь, что метод используется другим классом. Окей, это норма. Для чего он используется? Какую задачу другой класс хочет решить вызовом этого метода?
    Вопрос связан с тем, что ты почему-то создаёшь элементы управления в методе put_wigets(). По идее, если твой класс представляет собой группу элементов управления, он должен создавать дочерние элементы в своём конструкторе, и сохранять ссылки на них в приватные (ну, насколько это можно в питоне) поля класса. Методы класса должны к этим полям обращаться. Исходи из того, что локальная переменная в методе (как Ent_numberBox ) живёт только во время вызова этого метода, и не должна содержать ничего, что переживёт этот метод (если это не возвращаемое значение).

    Например, так:
    import tkinter as tk
    
    class InputBox(tk.Frame):
        def __init__(self, master, **kwargs):
            # вызываем унаследованный конструктор
            super().__init__(master, **kwargs)
            # переменные tkinter можно связывать с элементами управления
            # тогда изменение в переменной отобразится в элементе, и наоборот
            # это бывает удобнее, чем дёргать элемент напрямую
            # а ещё можно самим реагировать на изменения значения такой переменной
            self.__value = tk.StringVar()
            # наше поле ввода
            self.__entry = tk.Entry(self, justify=tk.RIGHT, width=22, textvariable=self.__value)
            self.__entry.pack(side=tk.RIGHT, padx=10, pady=15)
            # метка с пояснением
            self.__helptext = tk.Label(self, bg=self['background'], height=3, text="Введите мат. выражение:")
            self.__helptext.pack(side=tk.LEFT)
        
        def get_value(self) -> str:
            """Возвращает введённую строку."""
            return self.__value.get()  # метод get() позволяет прочитать значение переменной tkinter
        
        def set_value(self, value: str) -> None:
            """Заменяет содержимое введённой строки новым."""
            self.__value.set(value)  # метод set() позволяет задать новое значение для переменной
            
        def append(self, symbol: str) -> None:
            """Добавляет символ(ы) к уже введённой строке."""
            self.__value.set(self.__value.get() + symbol)
    
    
    if __name__ == '__main__':
        root = tk.Tk()
        box = InputBox(root)
        box.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
        box.set_value('Hello')
        box.append(', world!')
        root.mainloop()


    Я в этом примере исходил из своего понимания твоей задачи.
    Если это поле ввода, то мы хотим иметь возможность получить введённое значение. Поэтому метод get_value().
    Также ты упомянул необходимость в том, чтобы изменить это значение извне, из другого класса. Значит, нужен метод set_value().
    Также, если это - часть калькулятора, у тебя будет часто встречаться задача "добавить один символ в конец строки". Это можно реализовать через пару get_value()/set_value(), но будет удобнее иметь отдельный метод append().
    Один метод - одна решаемая задача.
    Ответ написан
    3 комментария
  • Как запихнуть в threading.Timer() async-функцию?

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

    Vindicar
    @Vindicar
    RTFM!
    JSON-объекты загружаются в простой питоновский словарь (а массивы - в список).
    Так что окей, гугл, перебор элементов словаря python.

    В твоём случае что-то вроде
    pages = info["query"]["pages"]
    for page_id, page_data in pages.items():
        ...   # что-то делаешь с page_id и page_data


    Если ты уверен, что у тебя всегда ровно один элемент в словаре, и его ключ тебя не интересует, то можно и так:
    pages = info["query"]["pages"]
    if pages:  # есть что-то в словаре?
        page_data = list(pages.values())[0]
        ...   # работаешь с page_data
    Ответ написан
    1 комментарий
  • Как запустить скрипт используя subprocess и venv из которого запущен главный скрипт?

    Vindicar
    @Vindicar
    RTFM!
    Найди бинарник python, который лежит в этом venv, и укажи его полный путь вместо просто python.
    Но так как ты дожидаешься завевршения скрипта, может иметь смысл такой хак:
    # my_script.py
    import sys
    
    def main(args: list[str]):
        """Тело скрипта здесь..."""
    
    if __name__ == '__main__':
        # скрипт запущен независимо
        main(sys.argv[1:])

    А в главном скрипте будет просто
    import my_script
    
    my_script.main(['--work-dir', work_dir, '--result-dir', result_dir])


    В этом случае тебе не придётся сильно переделывать my_script. Но зато теряешь в удобстве вызова кода, например, если нужно получить значение из этого скрипта.
    Чем больше ты вынесешь из main() в отдельные подпрограммы - тем больше контроля будет у главного скрипта, но и тем больше работы.
    Ответ написан
    Комментировать
  • Почему не получается передать значение в экземпляр класса?

    Vindicar
    @Vindicar
    RTFM!
    self.ship = Ship(screen)
    Ты пытаешься передать в конструктор Ship() локальную переменную screen, которой у тебя нет.
    Тут не C#, если обращаешься к полям класса - явно указывай self.
    Ответ написан
    3 комментария
  • Почему приложение, собранное с помощью Pyinstaller, не находит добавленный в сборку исполняемый файл?

    Vindicar
    @Vindicar
    RTFM!
    subprocess.Popen(("./ffmpeg.exe", …))
    Ты просишь запустить файл ffmpeg.exe, находящийся в текущем каталоге. Текущий каталог может и не совпадать с каталогом, в который pyinstaller распаковал твоё приложение. Почитай, что такое относительный и абсолютный путь.

    Чтобы получить этот каталог, попробуй такой приём из документации:
    import sys
    from pathlib import Path
    
    if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):  # мы запакованы pyinstaller?
        TEMP_DIR = Path(sys._MEIPASS).resolve()  # да - берем каталог приложения
    else:  # нет, мы не запакованы
        TEMP_DIR = Path(sys.argv[0]).parent.resolve()  # берем просто каталог скрипта
    # resolve() делает путь абсолютным, так что при смене текущего каталога путь не сломается
    ffmpeg_path = str(TEMP_DIR / "ffmpeg.exe")  # предполагаю, что ffmpeg лежит не в подкаталоге
    ffmpeg = subprocess.Popen((ffmpeg_path, …))
    Ответ написан
    1 комментарий
  • Почему Discord бот перестает отвечать?

    Vindicar
    @Vindicar
    RTFM!
    Может, уже неакутально, но отвечу.

    asyncio.create_task(bot.start(TOKEN))
    Созданный объект-таск может быть тут же собран garbage collector'ом, так как ты не хранишь ссылку на него. Разумеется, при этом сам таск (в твоём случае бот) прибьётся.
    Сохрани возвращаемый create_task() объект хотя бы в локальную переменную.
    Ответ написан
    Комментировать
  • Дискорд бот на питон не видет команды, почему это может быть?

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

    Вот что тут скажешь кроме "выучи язык сначала"?
    Почитай документацию, как пользоваться когами.
    Ответ написан
    Комментировать
  • Как правильно регистрировать ID пользователя через телеграмм?

    Vindicar
    @Vindicar
    RTFM!
    По твоей схеме - никак. Или бот должен заранее знать ID пользователя, или пользователь должен доказать, что логин - его.

    Я бы на сайте генерил пользователю уникальный одноразовый код и сохранял бы его в БД.
    А в боте по /start выводил бы сообщение, мол, введите свой код. При вводе кода ищи его в БД, если нашел - помечаешь пользователя как зареганного и записываешь его ID.
    Нужно будет навесить пару прибабахов типа возможности запросить новый код, защиту от попыток перебора кодов, и т.п., но суть от этого не меняется.
    Ответ написан
    1 комментарий
  • Как определить большинство и меньшинство по числовой характеристике?

    Vindicar
    @Vindicar
    RTFM!
    Т.е. ты ищешь выбросы (outliers) в данных? Ну вот в этом направлении и гугли. Можно начать с чего-то попроще, скажем, доверительного интервала.
    Или другой подход: если у тебя есть примеры таких наборов данных (а их надо иметь! вслепую много не напишешь), то ты можешь оценить закон распределения расстояний. Например, будет ли распределение похоже на нормальное (гауссово)? Если будет то можно будет оценить параметры распределения (среднее и дисперсию), и для каждого из значений оценить его вероятность. Например, значение, близкое к среднему, будет иметь высокую вероятность, а далёкое от среднего - низкую. Тогда можно будет по некоторому выбранному порогу отсекать "маловероятные" значения.
    Но это будет работать только для достаточно больших групп, хотя бы несколько десятков человек. Для трёх с половиной человек результаты будут очень неточными.
    Ответ написан
    2 комментария
  • Как имитировать физическое движение мыши?

    Vindicar
    @Vindicar
    RTFM!
    Сделай USB-устройство на базе arduino или чего-то подобного, которое имитирует мышь с точки зрения ОС и позволяет управлять собой через какой-то отдельный интерфейс. Всё остальное детектится при желании. А у разрабов игр желание детектить и банить ботов нередко присутствует.
    Ответ написан
    Комментировать