Задать вопрос
  • Как заставить дискорд бота запустить песню?

    Vindicar
    @Vindicar
    RTFM!
    Ну тебе бот пишет прямым текстом где он ищет библиотеку:
    OSError: dlopen(opus, 0x0006): tried: 'opus' (no such file), '/usr/local/lib/opus' (no such file), '/usr/lib/opus' (no such file), '/Users/similization/Programming/python/discord_bot/opus' (no such file)

    Найди, куда именно установился опус, и создай символическую ссылку на библиотеку по одному из указанных путей. Лучше всего по последнему, я полагаю.
    Ответ написан
  • Почему пул запускает тг бота хотя этого нет в def?

    Vindicar
    @Vindicar
    RTFM!
    Без полного кода ответить затруднительно, но...
    Проверь, завёрнуто ли у тебя тело бота в if __name__ == '__main__':
    Ответ написан
    2 комментария
  • Как отслеживать изменение даты файла с сайта?

    Vindicar
    @Vindicar
    RTFM!
    Если искомый файл доступен по ссылке, можно попробовать делать HEAD-запрос к нему и анализировать заголовок ответа Last-Modified. Если сервер его отдаёт, этот заголовок будет содержать дату и время последнего изменения файла.
    Альтернативно, можно добавить к обычному GET-запросу заголовок If-Modified-Since. В этом случае сервер даст разные ответы, если файл был модифицирован после указанного в заголовке момента времени, и если он не был. Опять же, нужно проверять на конкретном сервере, настройки могут отличаться.
    Ответ написан
    Комментировать
  • Как настроить локальный Django сервер если есть проблемы с электричеством?

    Vindicar
    @Vindicar
    RTFM!
    1. Многие модели материнских плат имеют в BIOS/UEFI настройку "Power On State", т.е. что делать, когда пропало а потом восстановилось электропитание. Типичные опции "Off" (остаться выключенной), "Restore" (включиться, если на момент пропадания питания была включенной), "On" (включиться всегда). Лезь в биос своей материнки и смотри, есть ли она.
    2. Настрой автозапуск для Django-сервера, в зависимости от того, какая ОС. Для линуксов это будет systemd модуль или init-v скрипт. Для винды можно использовать планировщик задач или утилиту NSSM, чтобы превратить скрипт в службу (это если у тебя django работает на своём встроенном сервере). Если же у тебя Django-скрипт выполняется как WSGI-приложение к обычному серверу (скажем, Apache), то утсановщик апача обычно об автозапуске заботится сам.
    Ответ написан
    Комментировать
  • Помощь с кодом. (discord.py/python), Упоминания в эмбеде?

    Vindicar
    @Vindicar
    RTFM!
    description='Администратор:{message.author.name}\nИгрок:{user.mention}\nВыданная роль:{role}'

    Это не f-строка, это обычная строка, в ней подстановка не выполняется. Ты f забыл в начале.
    Ответ написан
    Комментировать
  • Как решить такую задачу на python?

    Vindicar
    @Vindicar
    RTFM!
    Для каждого символа c в строке построй список вида [c.upper(), c.lower()], если это буква. Если не буква, список должен содержать один элемент.
    Построй общий список из таких списков (назовём его patterns). Для твоего примера он будет выглядеть так:
    [['a', 'A'], ['.'], ['b', 'B'], ['c', 'C'], ['@'], ['d', 'D']]

    А дальше вызываешь itertools.product(*patterns) и итерируешься по тому, что оно вернёт.
    Ответ написан
    1 комментарий
  • Как вывести в чат боте входные данные в сообщении?

    Vindicar
    @Vindicar
    RTFM!
    Ну смотри внимательно на структуру.
    Сделаем переменную all_lessons = [], куда будем складывать результат.
    Верхняя структура данных - кортеж (tuple). Элементы кортежа - уроки (идут по вертикали).
    Т.е. циклом вида for lesson in data: можно будет перебрать уроки.

    Теперь смотрим отдельный урок:
    [
      [['6']], # индекс 0 - номер урока (почему-то в двух списках)
      [], #индекс 1 - понедельник
      [['Физкультура'], ['Храпов О.Е.'], ['12:05 - 12:45'], ['216']], #индекс 2 - вторник
      [['Иностранный ...'], ['Севостьянова Е....'], ['12:05 - 12:45'], ['047']], #индекс 3 - среда
      [['Физкультура'], ['Храпов О.Е.'], ['12:05 - 12:45'], ['216']], #индекс 4 - четверг
      [], #индекс 5 - пятница
      [], #индекс 6 - суббота?
      [], #индекс 7 - ?
      []  #индекс 8 - ?
    ],


    Отсюда можно сделать вывод, что номер урока можно достать так: lesson[0][0].
    Далее, идёт цикл по дням недели
    for day_number in range(1, 7): #1 - понедельник
        lesson_per_day = lesson[day_number]


    Теперь рассмотрим, что попадёт в lesson_per_day. Тут есть три варианта:
    1. пустой список, урока нет
    2. В списке 4 элемента, один и тот же урок
    3. В списке 8 элементов, это или мигающее занятие (по неделям), или занятие по подгруппам (тебе виднее).
    [
       ['Технология'], #0 - что
       ['Бирюкова Е.Н.'], # 1 - кто
       ['16:15 - 16:55'], # 2 - когда
       ['133'], # 3 - где
       ['Технология'],  #4 - что (альтернатива)
       ['Горбунова Е.П.'], # 5 - кто (альтернатива)
       ['16:15 - 16:55'], # 6 - когда (альтернатива)
       ['048'] # 7 - где (альтернатива)
    ]

    Отсюда:
    if len(lesson_per_day) == 4: # есть одно занятие?
        all_lessons.append({
            'number': int(lesson[0][0]),
            'day': day_number,
            'subject': lesson_per_day[0],
            'teacher': lesson_per_day[1],
            'time': lesson_per_day[2],
            'room': lesson_per_day[3],
            'type': ''  # занятие не над/под чертой
        })
    elif len(lesson_per_day) == 8: # есть два занятия?
        all_lessons.append({
            'number': int(lesson[0][0]),
            'day': day_number,
            'subject': lesson_per_day[0],
            'teacher': lesson_per_day[1],
            'time': lesson_per_day[2],
            'room': lesson_per_day[3],
            'type': 'над чертой'
        })
        all_lessons.append({
            'number': int(lesson[0][0]),
            'day': day_number,
            'subject': lesson_per_day[4],
            'teacher': lesson_per_day[5],
            'time': lesson_per_day[6],
            'room': lesson_per_day[7],
            'type': 'под чертой'
        })

    Собери это вместе и в итоге получишь список словарей вида:
    [
        {'number': 6, 'daynumber': 1, 'subject': 'Физкультура', 'teacher': 'Храпов О.Е.', 'time': '12:05 - 12:45', 'room': '216', type: ''},
        {..................},
        .....................
    ]

    С этим списком уже делай что тебе надо: в базу сохраняй, отсеивай по number/daynumber, выводи... С ним будет проще работать.
    Ответ написан
  • SyntaxError: Non-UTF-8 code starting как исправить ошибку?

    Vindicar
    @Vindicar
    RTFM!
    Файл .py должен быть либо в кодировке ASCII (читай - никакой кириллицы и прочих национальных алфавитов), либо в кодировке UTF-8.
    Если у тебя кодировка не такая (а я подозреваю, у тебя стандартная виндовая ANSI, она же Windows-1251), то нужно явно указать кодировку в начале файла. Что-то типа
    # -*- coding: windows-1251 -*-
    Но я бы посоветовал взять нормальный текстовый редактор и сохранить файл в UTF-8. Меньше проблем.

    Ну собственно я готов спорить, что после "see" шла ссылка, которую ты не открыл.
    Ответ написан
    1 комментарий
  • Как определить размер объекта на фото при помощи python?

    Vindicar
    @Vindicar
    RTFM!
    Смотри в сторону OpenCV. Какой конкретно метод - зависит от искомого объекта: один ли он в кадре, насколько он контрастен по отношению к фону, насколько много на нём контрастных деталей, и т.д.
    Есть template matching для случаев, когда видимый размер и ориентация известны. Работает для нескольких объектов.
    Есть feature matching, для случаев, когда объект только один и имеет контрастные, узнаваемые элементы, но может быть разного размера и ориентации.
    Есть каскады Хаара (или тут) для поиска множества объектов известной ориентации, но с варьируемым размером.
    Есть backprojection, если объектов несколько, но они имеют характерный, узнаваемый набор цветов.
    Копай, разбирайся, выбирай.

    Если же вопрос в том, чтобы определить масштаб снимка, то тут самый простой способ - использовать шахматный шаблон с заранее известным размером ячейки и числом строк/столбцов. Тогда можно будет оценить расстояние между углами шаблона в пикселах, и сопоставить его с размером объекта в том же кадре. Заодно можно будет попробовать исправить перспективные искажения (попробовать переделать снимок в "вид строго сверху").
    Ответ написан
    5 комментариев
  • Как передать из функции в другую переменную не вызывая ее?

    Vindicar
    @Vindicar
    RTFM!
    С учётом контекста твоих предыдущих вопросов - ты пытаешься реализовать мой совет, но получается плохо.
    Смотри.

    #сначала реализуем механизм, который позволяет получать объект дневник для пользователя
    import typing
    from functools import lru_cache
    # говорим, что результаты вызова функции должны кэшироваться,
    # но храниться в кэше должно не более 50 экземпляров класса Dnevnik
    # при появлении новых экземпляров, самые старые будут выкинуты
    @lru_cache(maxsize=50)
    # принимаем ID пользователя Telegram, возвращаем или объект Dnevnik, или None
    def get_user_dnevnik(user_id) -> typing.Optional[Dnevnik]:
        # получаешь новый курсор для своего соединения с БД
        # я фз как у тебя называется глобальная переменная, хранящая соединение, 
        # так что назвал её db_conn. Поправишь
        cursor = db_conn.cursor()
        # выбираем из таблицы логинов/паролей пару, соответствующую указанному пользователю
        # имена таблицы и столбцов опять таки поправь, я не помню как они у тебя называются
        cursor.execute("SELECT loginD, passwordD FROM users WHERE id = ?", (user_id,))
        row = cursor.fetchone()
        if row is None: # нет такого пользователя, возвращаем None
            return None
        # в запросе порядок столбцов сначала логин, потом пароль, так что row = (логин, пароль)
        return Dnevnik(login=row[0], password=row[1]) # возвращаем объект Dnevnik


    Теперь, всякий раз, когда тебе требуется объект Dnevnik для пользователя с известным id, вызываешь функцию
    get_user_dnevnik(), передав ей в параметрах этот id.
    Поскольку мы указали для функции lru_cache, фактически запрос к БД и конструирование объекта Dnevnik будет выполняться только если в кэше нет дневника для пользователя с этим id. А если он есть, то дневник будет быстренько возвращён из кэша.
    В то же время кэш будет расти не беспредельно, его размер мы явно задаём и можем подогнать под свои нужды, чтобы балансировать потребление кэшем памяти и потребление проца повторным созданием экземпляров Dnevnik.
    Ответ написан
    Комментировать
  • Вопросик вселенского масштаба. Как добавить данные в БД Django?

    Vindicar
    @Vindicar
    RTFM!
    Сделай так, чтобы по нажатию на Добавить генерировался фоновый запрос через JS, передающий id книги.
    На бэкэнде сделай роут для этого запроса, и в нём уже выполняешь нужные действия.
    Ответ написан
  • Чем можно находить незакрытый html тэг?

    Vindicar
    @Vindicar
    RTFM!
    from html.parser import HTMLParser
    
    bufer = '''<p>
        <div>hi!
    </p>'''
    
    class MyHTMLParser(HTMLParser):
        def __init__(self):
            super().__init__()
            self.open_tags = []
        
        def handle_starttag(self, tag, attrs):
            print("Start tag:", tag)
            self.open_tags.append((tag, self.getpos()))
        
        def handle_endtag(self, tag):
            print("End tag  :", tag)
            unclosed_tags = []
            # ищем, когда был открыт нужный тег
            for i in range(len(self.open_tags)-1, -1, -1):
                if self.open_tags[i][0] != tag:
                    unclosed_tags.append(self.open_tags[i])
                else:
                    break
            if len(unclosed_tags) == len(self.open_tags): # тег никогда и не был открыт
                print(f"Closing tag {tag} has no matching opening tag!")
            elif unclosed_tags: # тег был открыт, но он не последний
                print("Following tags are not closed properly:\n", '\n'.join(f'    {t} at line {line} pos {col+1}' for t,(line, col) in unclosed_tags))
                del self.open_tags[-len(unclosed_tags)+1:] # сбрасываем незакрытые теги
            else: # тег был открыт, и он последний - всё в порядке
                del self.open_tags[-1]
        
        def close(self):
            super().close()
            print('Processing done')
    
    parser = MyHTMLParser()
    parser.feed(bufer)
    parser.close()


    Вместо вывода текста можешь сразу выкидывать исключения, или накапливать сведения об ошибках, чтобы выкинуть одно исключение с полной информацией в методе close().
    Ответ написан
    2 комментария
  • Почему ошибка UnboundLocalError: local variable 'loginD' referenced before assignment?

    Vindicar
    @Vindicar
    RTFM!
    Вообще-то да, эту ошибку тут часто спрашивают, хотя она очень простая.
    for row in records:
            loginD = row[2]
            passwordD = row[3]
    d = Dnevnik(login=loginD, password=passwordD)

    У тебя d создаётся после цикла, только для последнего значения loginD и passwordD.
    Вопрос: что будет, если в records ничего нет?
    Тело цикла не выполнится ни разу, переменные loginD и passwordD не будут определены. А ты дальше пытаешься их использовать, о чём питон и предупреждает.

    Ну и да, код - какой-то бред.
    1. Ты сначала делаешь records = cursor.fetchall(). Тем самым ты выбираешь все строки, возвращённые последним запросом, выполненным через cursor. При следующем вызове функции homeworkss() cursor уже не будет содержать строк (ты их все выбрал в прошлый раз). А следующий вызов может настать в любой момент, так как homeworkss() - обработчик события. Почему ты выполняешь запрос вне homeworkss()?
    2. Зачем вообще перебирать строки таким циклом, который создаёт дневник только для последней строки? Если тебе нужна конкретная строка, то почему не выбрать запросом только её? Если тебе нужны все строки, почему ты создаёшь дневник только для одной?
    Ответ написан
    Комментировать
  • Как мне продолжить изучение языков программирования?

    Vindicar
    @Vindicar
    RTFM!
    Я бы не советовал начинать с питона или с php, разве что программирование нужно выучить срочно, "ещё неделю назад, но вчера тоже сойдёт".
    Языки с динамической типизацией имеют свои преимущества, они удобны, но ИМХО они подразумевают, что программист умеет оперировать типами данных сам. Более строгие языки типа Java или C# всё-таки приучают думать о таких вещах самостоятельно. Самые основы (алгоритмы и структуры данных) лучше осваивать на них, а потом уже с этим базисом переползать на другие языки.
    Ответ написан
    3 комментария
  • Как получить названия всех ярлыков в папке?

    Vindicar
    @Vindicar
    RTFM!
    Ярлыки имеют расширение *.lnk.
    Для поиска файлов по расширению используй метод glob() класса pathlib.Path, ну или функцию glob.glob().
    Ответ написан
    Комментировать
  • ImportError: cannot import name 'enter_client' from partially initialized module 'handlers' Что я сделал не так?

    Vindicar
    @Vindicar
    RTFM!
    Если я комментирую импорт "from handlers import enter_client", в файле админа, то всё запускается, но естественно, функция работать не будет
    Если я комментирую импорт "from handlers import enter_admin", в файле клиент, то не работает, ссылаясь на ошибку (ImportError: cannot import name 'enter_client' from partially initialized module 'handlers')


    Циклический импорт, с чем тебя и поздравляю. Так делать нельзя.

    Определись уже с зависимостями, кто кому нужен? Зачем enter_client() ссылаться на контент из admin.py?
    Ответ написан
  • Не будет ли этот код блокировать асинхронный код?

    Vindicar
    @Vindicar
    RTFM!
    Проблема в том, что в Питоне потоки немножко увечные (ключевое слово GIL), а потому реально работают только в двух случаях:
    1. Исполняемый длительный код написан не на питоне, а принадлежит одному из бинарных модулей
    2. Исполняемый код большую часть времени ждёт (например, операции ввода/вывода).
    В случае с многопроцессностью проблем меньше, но появляетя проблема обмена данными между процессами.

    Я бы запустил несколько процессов воркеров, которые умеют рендерить предоставленные данные и возвращать график как массив байт, содержащий изображение. Тогда основной бот кидает задание в некую очередь, один из воркеров просыпается, рендерит задание, и кладёт ответ в другую очередь. Словом, паттерн поставщик-потребитель. Конечно, могут быть проблемы с тем, чтобы подружить multiprocessing.Queue с асинхронным кодом, но имхо так всё равно изящнее.
    Более того, если искомые данные лежат в БД или ином внешнем источнике - можно нагрузить воркеров их извлечением. Тогда задание будет содержать в себе только критерии выборки данных.
    Ответ написан
  • Как залезть внутрь тега?

    Vindicar
    @Vindicar
    RTFM!
    Это называется "поленился погуглить". Вопрос уже задавали много раз, в т.ч. тут.
    Вот мой недавний ответ на тот же вопрос.
    Сейчас далеко не 90е, и на большинстве страниц полно JS-скриптов. Они, в том числе, могут делать фоновые (без перезагрузки страницы) запросы по ходу работы сайта. Так, например, реализуется "бесконечная лента" - по достижению низа страницы делается фоновый запрос, и новый контент подставляется вниз.
    Некоторые сайты на этом вообще целиком построены - отдают основным запросом только болванку, а содержимое туда подсовывают фоновыми запросами. Как следствие, то, что ты выкачиваешь через requests, и то, что увидит пользователь в браузере - две большие разницы.
    Соответственно, тут нужно:
    1. Идентифицировать, какие фоновые запросы делает сайт. Инструменты разработчика в браузере в помощь.
    2. Определить, какие из этих запросов подгружают нужную тебе информацию, и в каком виде она представлена. Нередко там не HTML-разметка, а формат JSON, с которым куда проще работать.
    3. Определить, что нужно для выполнения этих запросов: какие URL дёргать, какие параметры подставлять, и т.д.
    4. Попробовать имитировать только эти запросы.
    Успех зависит от сайта, многие пытаются защищаться от такого, кто во что горазд.

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

    Vindicar
    @Vindicar
    RTFM!
    Можно дёргать функции WinAPI через ctypes, но pymem удобнее.
    Ответ написан
    Комментировать
  • Почему .append() добавляет неизмененные данные?

    Vindicar
    @Vindicar
    RTFM!
    nun[1]+=i
    possible.append(nun)
    nun[1]-=i

    Это не будет работать, так как append() добавляет ссылку на список, а не его копию.
    Попробуй выполнить вот такой код в отдельном файле и убедись
    b = []
    a = [1, 2, 3]
    b.append(a)
    b.append(a.copy())
    a.append(5)
    print(b)  # выведет [[1, 2, 3, 5], [1, 2, 3]]
    print(b[0] is a)  # выведет True, так как 0 элемент b - ссылка на a
    print(b[1] is a)  # выведет False, так как 1 элемент b - ссылка на отдельный список
    Ответ написан
    Комментировать