Ответы пользователя по тегу Python
  • Как сменить язык речи в голосовом ассистенте?

    Vindicar
    @Vindicar
    RTFM!
    Гуглить пробовал? На первой странице выдачи этот ответ на StackOverflow.
    Если коротко:

    Зависит от установленных на компе голосовых движков. Проверь доступные движки так:
    import pyttsx3
    
    engine = pyttsx3.init()
    for voice in engine.getProperty('voices'):
        print(voice)

    Ищи голоса, у которых упомянут русский язык. Если нет - гугли, как их ставить.

    Определившись с голосом, пропиши его id в скрипте, например
    # тут id голоса, который ты выбрал
    voice_id = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\MSTTS_V110_trTR_Tolga"
    engine = pyttsx3.init()
    engine.setProperty('voice', voice_id)
    Ответ написан
    Комментировать
  • Нужно ли закрывать сессию при requests?

    Vindicar
    @Vindicar
    RTFM!
    1. Чем не устраивают обозначенные варианты? Если токен должен переживать перезапуск, храни его в конфигурации. Если не должен, храни его только в памяти - в глобальной переменной или в атрибуте класса.
    2. Конечно стоит. Просто для того, чтобы при истечении токена на полпути его можно было перезапросить прозрачно для клиентского кода. Например, декоратор вида:
    def requires_token(func):
        @functools.wraps(func)
        def wrapper(self, *args, **kwargs):  #оборачиваем метод, а не функцию
            try:
                result = func(self, *args, **kwargs)  # пробуем вызвать метод как есть
            except InvalidToken:  # кастомное исключение, которое должны выбрасывать методы
                self._acquire_new_token()  # получаем новый токен
                result = func(self, *args, **kwargs)  # пробуем еще раз
            return result
    
        return wrapper

    Тогда любой декорированный метод, который выбрасывает исключение InvalidToken, спровоцирует автоматический запрос нового токена и одну повторную попытку выполнения операции.
    Но можно делать это и явно, в каждом методе.
    3. Под закрытием сессии ты понимаешь инвалидацию токена, т.е. невозможность его дальнейшего использования? Ну так это тебя нужно спрашивать, нужно ли закрывать сессию и требует ли используемое API явного закрытия сессии. Планируешь ли ты выполнять дальнейшие операции в рамках этой сессии? Если точно нет, можешь закрывать - например, при выходе из скрипта. Заодно снимется вопрос о хранении токена. Если не хочешь дёргать получение токена понапрасну, тогда храни токен, но не закрывай.
    Делать это в КАЖДОМ методе точно бессмысленно.
    Ответ написан
    5 комментариев
  • Как визуализовать результат работы кластеризации?

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

    Vindicar
    @Vindicar
    RTFM!
    list(zip(sess, tasks)) должно сгенерить список пар "сессия, задача". Дальше уже с каждой парой работаешь.
    Ответ написан
  • NoneType: 'NoneType' object is not subscriptable. Как быть, где допустил ошибку?

    Vindicar
    @Vindicar
    RTFM!
    msg = event.object.message
    user_id = msg['from_id']

    Значит, msg - это None.
    1. Читай документацию на используемую библиотеку, в каких случаях это может быть
    2. Выполняй операции только если if msg is not None:
    Ответ написан
    Комментировать
  • Как заставить дискорд бота запустить песню?

    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. В этом случае сервер даст разные ответы, если файл был модифицирован после указанного в заголовке момента времени, и если он не был. Опять же, нужно проверять на конкретном сервере, настройки могут отличаться.
    Ответ написан
    Комментировать
  • Как решить такую задачу на python?

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

    А дальше вызываешь itertools.product(*patterns) и итерируешься по тому, что оно вернёт.
    Ответ написан
    1 комментарий
  • 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.
    Ответ написан
    Комментировать
  • Чем можно находить незакрытый 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!
    Ярлыки имеют расширение *.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 с асинхронным кодом, но имхо так всё равно изящнее.
    Более того, если искомые данные лежат в БД или ином внешнем источнике - можно нагрузить воркеров их извлечением. Тогда задание будет содержать в себе только критерии выборки данных.
    Ответ написан
  • Почему .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 - ссылка на отдельный список
    Ответ написан
    Комментировать
  • Ошибка TypeError: marks_message() missing 1 required positional argument: 'marks' почему?

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


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

    Vindicar
    @Vindicar
    RTFM!
    Очень просто. Смотри на первый пример:
    product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    Генерятся комбинации из двух символов (так как два параметра). Причем первый параметр кодирует возможные первые символы, а второй - возможные вторые.

    Нам нужно только обобщить это.

    Идешь циклом по строке-маске и формируешь список, где каждый элемент - список подставляемых знаков, соответствующих текущему символу строки-маски. (Назовём этот список списков parts).
    А дальше просто делаешь цикл for combo in product(*parts):
    Ответ написан
    1 комментарий