Задать вопрос
Ответы пользователя по тегу Python
  • Как в python создать interface?

    Vindicar
    @Vindicar
    RTFM!
    typing.Protocol играет роль интерфейса, с той поправкой, что наследоваться от него потом необязательно - главное, чтобы набор полей/методов соответствовал.

    abc.ABC - это именно абстрактный класс, он требует наследование от себя для соответствия, и часто предполагает наличие какой-то частичной реализации функциональности.

    В отличие от него, typing.Protocol обычно применяется только для описания контракта класса, но не для частичной реализации. Так как он не требует наследования, он хорошо подходит для описания структуры объекты, который мы ожидаем на входе - без жётской привязки этого объекта к нашей иерархии классов.

    "Обычно", потому что и то, и то можно использовать "не по назначению".
    Ответ написан
    9 комментариев
  • TimeoutError: [WinError 10060] Python, куда копать?

    Vindicar
    @Vindicar
    RTFM!
    smpt.yandex.ru?
    Может, всё-таки smtp?
    Ответ написан
    Комментировать
  • При вводе команды в консоли отображается ошибка `NoneType` object is not supscriptable, что делать?

    Vindicar
    @Vindicar
    RTFM!
    f"""**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]}**"""

    За такое надо калечить.
    Во-первых, это абсолютно нечитаемый кусок кода. Вперемешку вывод пользователю, sql запрос и команды питона.
    Во-вторых, привычка использовать format() для составления SQL запросов приводит к весёлым последствиям, когда требуется подставить строку. Гугл "sql инъекция".
    В-третьих, ты не проверяешь, что вернул тебе fetchone(). С какого перепугу ты решил, что у тебя гарантируется наличие записи с таким id в таблице? Всегда исходи из того, что запрос может потерпеть неудачу, и продумывай, что бот должен делать в таком случае.
    Ответ написан
    Комментировать
  • Как перенести данные с Python в Excel?

    Vindicar
    @Vindicar
    RTFM!
    Окей, гугл, python create excel document. Находим xlsxwriter. Эту часть ты сделал.

    Дальше придётся прочитать (а не просто скопипастить) пример и чутка включить голову.
    import xlsxwriter
    
    # Create a workbook and add a worksheet.
    workbook = xlsxwriter.Workbook('Expenses01.xlsx')
    worksheet = workbook.add_worksheet()
    
    # Some data we want to write to the worksheet.
    expenses = (
        ['Rent', 1000],
        ['Gas',   100],
        ['Food',  300],
        ['Gym',    50],
    )
    
    # Start from the first cell. Rows and columns are zero indexed.
    row = 0
    col = 0
    
    # Iterate over the data and write it out row by row.
    for item, cost in (expenses):
        worksheet.write(row, col,     item)
        worksheet.write(row, col + 1, cost)
        row += 1
    
    # Write a total using a formula.
    worksheet.write(row, 0, 'Total')
    worksheet.write(row, 1, '=SUM(B1:B4)')
    
    workbook.close()

    Что мы видим в этом коде? Что метод worksheet.write() принимает в качестве параметров строку и столбец, куда нужно записать значения. Т.е. нам нет необходимости писать их в определённом порядке, мы можем их писать как нам удобнее.
    А чего мы НЕ видим? А мы не видим какого-либо задания лимитов по количеству строк/столбцов. Значит, мы не обязаны знать заранее, сколько строк/столбцов у нас будет в данных, а можем писать по мере поступления новых данных.

    Отсюда вывод: данная библиотека подходит нам до тех пор, пока мы для каждой порции данных можем сказать, в какую ячейку эта порция должна попасть, т.е. можем определить значения row и col. Обрати внимание, что в примере позиция (номер строки) просто хранится переменной и меняется по мере чтения данных, а номер столбца определяется в зависимости от записываемого элемента данных. Этот подход прекрасно подойдёт к описанной задаче, единственная разница - у тебя строки будут зависеть от элемента данных, а столбцы будут наращиваться по мере чтения входных данных.

    В чём сложность адаптировать этот пример к твоей задаче?
    Ответ написан
  • Парсинг сайта Яндекс.Музыка на Python, как?

    Vindicar
    @Vindicar
    RTFM!
    Если сайт не слишком защищается от парсеров и не требует JS для работы:
    requests для скачивания страницы, beautiful soup для разбора html документа и поиска элементов в нём.

    Если сайт требует JS для работы, можно пошариться в консоли разработчика в браузере и найти, какие запросы страница-фронт делает, чтобы подгрузить данные. Тогда ты можешь научиться делать точно такие-же запросы, и получать данные сразу в машинночитаемом виде (часто в JSON).

    Если сайт защищается от парсеров и JS логика слишком сложная, или он часто обновляется, можно попробовать selenium для эмуляции браузера. Дальше используешь инструменты selenium, чтобы найти интересующие тебя элементы на странице.

    Если сайт детектит selenium, нужно искать сборки селениума, которые труднее обнаружить. Тут я навскидку не подскажу.
    Ответ написан
    Комментировать
  • Почему PyCharm и VS code по-разному реагируют на одинаковые файлы?

    Vindicar
    @Vindicar
    RTFM!
    Почитай, что такое относительный путь, и что такое рабочий каталог.
    Это, на минуточку, школьный курс информатики.

    Ты указываешь относительный путь к файлу при открытии, поэтому путь разрешается относительно текущего рабочего каталога. Разные IDE могут указывать разные каталоги как рабочие при запуске скрипта, не говоря уже о том, что при запуске скрипта из терминала рабочим может быть любой каталог.
    А ещё рабочий каталог может меняться во время работы скрипта.

    Так что если тебе нужен путь к файлу именно рядом со скриптом, строй этот путь сам, используя модули sys и pathlib (ну или os.path, если по-старинке).
    import sys
    import pathlib
    # каталог, в котором лежит скрипт
    APP_DIR = pathlib.Path(sys.argv[0]).parent.resolve()
    # файл в этом каталоге
    my_file_path = APP_DIR / 'Token.txt'  
    
    with my_file_path.open('rt') as f:  # получаем файловый объект, как обычно
        data = f.read()
    Ответ написан
    Комментировать
  • Как проверить полученную случайную выборку в Python по ряду условий?

    Vindicar
    @Vindicar
    RTFM!
    Опиши правила генерации как конечный автомат. Например, так:
    rules = {
        # id_состояния: переходы
        # каждый переход - пара (набор_символов, следующее состояние)
        # будет выбран случайный переход, потом случайный символ из его набора символов
        # это начальное состояние. Можно генерировать любые символы.
        'default': [ (A, '1_vowel'), (B, '1_consonant') ], 
        # последний символ был гласной - следующая гласная будет последней
        '1_vowel': [ (A, '2_vowels'), (B, '1_consonant') ],
        # два последних символа были гласными - можем добавлять только согласные
        '2_vowels': [ (B, '1_consonant') ],
        # с согласными по аналогии
        '1_consonant': [ (A, '1_vowel'), (B, '2_consonants') ],
        '2_consonants': [ (A, '1_vowel') ],
    }

    Очевидно, правила могут быть и более сложными, такая схема это позволяет. Более того, можно описывать допустимые слоги и их сочетания вместо допустимых букв.
    А использовать их можно примерно так:
    from random import choice
    
    def generate(rules: dict[str, list[tuple[list, str]]], min_length: int) -> str:
        output = ''
        state = 'default'  # начальное состояние
        while len(output) < min_length:
            if not rules[state]:  # если нет переходов
                break  # прерываем цикл, так как уйти из этого состояния нельзя
            transition = choice(rules[state])  # случайно выбираем один из переходов
            output += choice(transition[0])  # случайно выбираем очередной символ согласно переходу
            state = transition[1]  # переходим в следующее состояние
        return output  # возвращаем то, что нагенерировали

    Тогда гарантируется, что сгенерированная строка будет соответствовать условиям.
    Ответ написан
    1 комментарий
  • Как человекообразно отсортировать json в python?

    Vindicar
    @Vindicar
    RTFM!
    Пересоздать ключи в словаре в правильном порядке и отключить дефолтную сортировку.
    Ответ написан
    1 комментарий
  • Как посчитать количество одинаковых цифр в 4-х значном числе?

    Vindicar
    @Vindicar
    RTFM!
    Составь коллекцию, в которой будет храниться набор пар: цифра и сколько раз она встретилась. Лучше всего подойдёт словарь.
    Дальше просто перебери элементы словаря, если есть элемент, у которого значение равно 3, значит, число подходит.

    Совет: посмотри в сторону collections.Counter.
    Ответ написан
    Комментировать
  • Как сделать выбор папки в скрипте?

    Vindicar
    @Vindicar
    RTFM!
    import tkinter as tk
    from tkinter import filedialog as fd
    
    root = tk.Tk()  # пустое родительское окно
    root.withdraw()  # прячем его
    result = fd.askdirectory(
        master=root,   # диалогу нужно родительское окно, путь даже невидимое.
        mustexist=True)  # только существующие каталоги
    root.destroy()  # уничтожаем родительское окно
    print(type(result), repr(result))  # result будет содержать путь или пустую строку при отмене
    Ответ написан
    Комментировать
  • Почему выдаёт ошибку No module named 'javascript'?

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

    Vindicar
    @Vindicar
    RTFM!
    1. Включи логику.
    2. Рукалицо.
    3. Поменяй эти две строки местами.

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

    Vindicar
    @Vindicar
    RTFM!
    Я тебе вроде уже кидал один вариант.
    По ссылке приведён пример использования, он показывает, как превратить "пять минут" в "5 минут".

    А дальше уже черёд регулярных выражений. Что-то в духе ([0-9.,]+)\s*(секунд\w*|минут\w*|час\w*) позволит выбрать набор частей интервала времени.
    import re
    text = 'поставь таймер на 6 часов 12 минут 5 секунд'
    regexp = re.compile(r"([0-9.,]+)\s*(секунд\w*|минут\w*|час\w*)", re.I)
    parts = list(regexp.findall(text))
    print(parts)  # [('6', 'часов'), ('12', 'минут'), ('5', 'секунд')]

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

    Vindicar
    @Vindicar
    RTFM!
    result = f'Уложите плазму в шокерную'
    Во-первых, от того, что ты присвоил переменной строку, в окне программы ничего не изменится.
    Во-вторых, у тебя этот result инициализируется только внутри этого if. Если условие if не выполнено, result не будет существовать, на что тебе питон и указывает.
    Ответ написан
    Комментировать
  • Как просто сделать неблокируемое взаимодействие с питоновским процессом?

    Vindicar
    @Vindicar
    RTFM!
    Пусть программа пишет в stdout или в stderr текущее положение дел.
    Ну или в отдельный временный файл. OpenVPN так делает, например.

    Особенность такого подхода в том, что программа сама решает, когда обновить эту инфу.
    Ответ написан
    Комментировать
  • Python discord как удалить сообщение?

    Vindicar
    @Vindicar
    RTFM!
    Ответ написан
    Комментировать
  • Как конвертировать байты(шестнадцатеричный код) в string в Python?

    Vindicar
    @Vindicar
    RTFM!
    Если именно байты, то так:
    b = b'\x68\x65\x6c\x6c\x6f'
    print(b.decode('ascii'))  # hello

    Фокус в кодировке. Если у тебя не только ASCII, то нужно точно знать, в какой кодировке данные. Например, utf-8, или latin-1, или windows-1251. Или ещё какой, их 100500.
    А если данные битые, то декодирование не гарантируется.
    Ответ написан
    Комментировать
  • Как работает asyncio.sleep?

    Vindicar
    @Vindicar
    RTFM!
    Идея простая.
    Асинхронные приложения - это набор пар "операция - обработчик", где операция - это некоторый длительный процесс (скажем, вводы/вывод), который не требует постоянного внимания со стороны кода. Когда операция завершается, выполняется её обработчик. Этот обработчик может планировать другие операции, и так далее.

    Корутины - это такие функции, которые умеют сохранять своё состояние, и восстанавливать его. Т.е. когда корутина делает await-вызов, она начинает длительную операцию, а обработчик этой операции просто восстанавливает контекст корутины и продолжает её выполнение.

    Соответственно, await-вызов сохраняет текущий контекст корутины, и планирует новую длительную операцию. Какую - зависит от того, что идёт после await. Эта операция представлена тем или иными awiatable значением (Future, Task и т.п.).

    Рабочий цикл (loop, его также называют реактор) просто проверяет текущие операции. Как только одна из них завершилась, он выполняет её обработчик. А потом продолжает проверять остальные активные операции.

    Ключевой момент - выполняет обработчик, а только потом проверяет остальные операции. Т.е. если обработчик планирует операцию через await - это не проблема, она будет выполняться наравне с остальными. А вот если обработчик просто делает что-то длительное, он не возвращает управление циклу, и не даёт выполняться остальным операциям.

    asyncio.sleep() планирует ничего не делающую операцию, которая завершится успехом через заданное время. Поэтому её выполнение не мешает циклу-реактору. Просто ещё один await вызов, который приостанавливает текущую корутину и возвращает управление реактору.

    time.sleep() ничего не знает о реакторе и асинхронных операциях. Она приостанавливает выполнение обработчика, не прерывая его и не отдавая контроль реактору. Поэтому на время time.sleep() (или любой длительной синхронной операции) спит вся программа.
    Ответ написан
    5 комментариев
  • Не понимаю почему не работает код python, не могли бы пожалуйста объяснить!?

    Vindicar
    @Vindicar
    RTFM!
    при введении пароля выводит ошибку string index out of range и я понимаю что это означает что
    в [] в листе не существующий индекс

    Нет, не понимаешь. Тебе же прямо сказано про строку, а не про список.
    Ты сначала делаешь i = plst[ii], а потом с какого-то перепугу делаешь i[ii].isupper() and not i[ii].isnumeric().
    У тебя i - это уже один символ, так как plst содержит строку, разбитую по символам.
    Ответ написан
    Комментировать
  • Как сделать активацию по спискам?

    Vindicar
    @Vindicar
    RTFM!
    Давай-ка я тебе покажу как я бы эту проблему решил. А уж осилишь или нет...

    Идеи:
    1. Разные команды должны быть независимы друг от друга.
    2. Проверка совпадения текста с командой и выполнение самой команды - разные задачи.
    3. Список команд не должен быть захардкожен.
    4. Код, нужный для реализации и добавления команды, должен быть по возможности сосредоточен в одном месте.
    5. Следует избегать необходимости повторять один и тот же код в обработчиках и предикатах. Это позволит упростить их.

    Следствия:
    1. Каждая команда должна быть отдельной подпрограммой - обработчиком команды.
    2. Для каждого обработчика команды должна существовать отдельная подрограмма - предикат команды. Она проверяет, подходит ли произнесённый текст под команду.
    3. Нужно хранить коллекцию (например, список - list) пар "обработчик - предикат". При работе бот будет перебирать этот список, ища подходящую пару. Должен быть механизм внесения пары в этот список (регистрация обработчика).
    4. Следует предусмотреть возможность регистрации с помощью декораторов. Это удобно и позволяет разместить описание обработчика и его регистрацию рядом, неотрывно друг от друга.
    5а. Основной бот должен заниматься вопросами распознавания речи, проверки наличия ключевого слова (имени бота), вызова предикатов для определения обработчика и возврата ответа пользователю (через консоль или синтез речи).
    5б. Стоит предусмотреть способ автоматического конструирования простых предикатов вроде "текст начинается с указанного слова/слов".

    Отсюда мы получаем следующее...
    Код

    import typing as t
    import speech_recognition as sr
    
    
    # предикат принимает текстовую строку и возвращает истину или ложь
    # истина значит "я понимаю эту строку, мой обработчик с ней справится".
    PredicateFunc = t.Callable[[str], bool]
    # обработчик принимает объект бота и текстовую строку команды. Он не возвращает ничего.
    HandlerFunc = t.Callable[['VoiceBot', str], None]
    
    
    class VoiceBot:
        """Основной класс бота."""
        
        def __init__(self, name: str):
            """Конструктор вызывается при создании экземпляра бота."""
            self._name: str = name.lower()  # любая команда должна начинаться с имени бота
            # список известных боту обработчиков
            self._handlers: t.List[t.Tuple[PredicateFunc, HandlerFunc]] = []
            # тут будут другие поля, нужные для работы класса бота
            # ты ведь знаешь, как работают классы в питоне?
            self._recognizer = sr.Recognizer()
        
        def say(self, text: str) -> None:
            """Обработчики могут вызвать say(), чтобы бот что-нибудь сказал или написал."""
            print(text)  # пока что бот просто пишет ответ в консоль
        
        def register(self, condition: t.Union[str, t.List[str], PredicateFunc]):  # принимает строку, список строк или готовую функцию-предикат
            """Этот метод используется как декоратор для регистрации обработчика.
            Он может принимать как готовую функцию-предикат, так и просто строку/строки, с которых должна начинаться команда.
            В этом случае он подготовит нужный предикат самостоятельно.
            """
            if isinstance(condition, str):  # получили строку? переделаем её в предикат
                s_lower = s.lower()
                
                def predicate(text: str) -> bool:  # объявления функций могут быть вложенными
                    return text.lower().startswith(s_lower)  # если команда начинается с этой строки
                
            elif isinstance(condition, (list, tuple)):  # получили список строк
                strings_lower = [s.lower() for s in condition]  # делаем список строк в нижнем регистре
                
                def predicate(text: str) -> bool:  # объявления функций могут быть вложенными
                    return any(text.lower().startswith(s) for s in strings_lower)  # если любая из строк подошла
                
            else:  # получили готовую функцию-предикат - используем её как есть
                predicate = condition
            
            def decorator(handler: HandlerFunc):  # фактический декоратор получит на вход функцию-обработчик
                self._handlers.append((predicate, handler))  # запоминаем пару предикта-обработчик
                return handler  # декоратор должен вернуть функцию
            
            return decorator
        
        def _find_correct_handler(self, command: str) -> t.Union[HandlerFunc, None]:
            """Этот метод определяет, какой из известных обработчиков подойдёт к команде command."""
            for predicate, handler in self._handlers:
                try:
                    if predicate(command):  # предикат сказал "да"
                        return handler  # значит, этот обработчик и будем использовать
                except Exception as err:  # что-то пошло не так с предикатом
                    print(f'Predicate error for handler {handler!r}', err)  # сообщаем об ошибке, ищем дальше
            # если дошли досюда, мы не нашли подходящий обработчик
            return None  # вернём None как признак неудачи
        
        def do_one_command(self):
            """Этот метод запишет и обработает одну команду."""
            try:
                with sr.Microphone(device_index = 1) as source:
                    print('Настраиваюсь.')
                    self._recognizer.adjust_for_ambient_noise(source, duration=0.6)
                    print('Слушаю...')
                    audio = self._recognizer.listen(source)
                print('Услышал.')
                query = self._recognizer.recognize_google(audio, language = 'ru-RU')
            except Exception as err:  # никогда не "глотай" ошибки - хотя бы выведи их в журнал ,если не знаешь, что с ними делать.
                self.say('Ошибка при записи/распознавании!')  # даём знать пользователю
                print(err)  # это сообщение об ошибке нужно будет проанализировать, чтобы понять где ошибка
                return
            text = query.lower()
            print(f'Вы сказали: {text}')
            if not text.startswith(self._name):  # текст начинается не с нашего ключевого слова (имени) - игнорируем
                return
            text = text[len(self._name):].strip()  # убираем имя из текста
            handler = self._find_correct_handler(text)  # ищем обработчик
            if handler is None:  # не нашли
                self.say("Я не понимаю, что вы хотите.")  # так и говорим пользователю
                return
            # если дошли досюда - значит нашли
            try:
                handler(self, text)  # вызываем обработчик команды
            except Exception as err:  # он может потерпеть неудачу
                self.say("Произошла ошибка")  # так и говорим пользователю
                print(err)  # это сообщение об ошибке нужно будет проанализировать, чтобы понять где ошибка



    А вот пример использования:
    if __name__ == '__main__':
        import webbrowser 
        
        bot = VoiceBot('ботва')  # "Ботва" - ключевое слово (имя) бота.
        
        # описываем и регистрируем обработчик команды
        @bot.register(['открой контакт', 'открой вк'])  # должен сработать на "ботва открой контакт", например
        def command_vk(bot, text):
            webbrowser.open('https://vk.com', new=1)
            bot.say('Готово.')
        
        # рабочий цикл бота
        while True:
            bot.do_one_command()

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

    Как работают декораторы?

    Если коротко, то вот этот код:
    @bot.register(['открой контакт', 'открой вк'])
    def command_vk(bot, text):
        webbrowser.open('https://vk.com', new=1)
        bot.say('Готово.')

    эквивалентен вот такому коду:
    _decorator_func = bot.register(['открой контакт', 'открой вк'])  # готовим функцию-декоратор
    
    def command_vk(bot, text):  # описываем декорируемую функцию
        webbrowser.open('https://vk.com', new=1)
        bot.say('Готово.')
    
    _decorated_func = _decorator_func(command_vk)  # вызываем декоратор на этой функции
    command_vk = _decorated_func  # заменяем декорируемую функцию на то, что вернул декоратор



    Да, боты - это ни разу не просто.
    Ответ написан
    Комментировать