Задать вопрос
  • Почему 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.
    Ответ написан
    Комментировать
  • Как найти COM порт оптимально?

    Vindicar
    @Vindicar
    RTFM!
    Во-первых, ардуино (ну как минимум китайские клоны) отдают определённый VID/PID USB устройства. Этим можно пользоваться для сужения диапазона поиска. Эту инфу можно узнать из реестра Windows.
    Во-вторых, если ты контролируешь прошивку ардуинки, можешь заставить её отправлять какой-то хэндшейк (заранее известный пакет) при подключении к порту (обычно арудино перезагружается при коннекте к порту). Тогда достаточно подождать совсем чуть-чуть, отправка данных не потребуется. Также меньше шансов что-то поломать, отправив левые данные в неизвестное устройство.
    В-третьих, просто сделай два последовательных цикла - один создаёт и запускает потоки, а второй их дожидается. Тогда ожидание будет параллельным.
    Ответ написан
    2 комментария
  • Как сделать выбор папки в скрипте?

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

    Vindicar
    @Vindicar
    RTFM!
    Чем не устраивает
    SELECT * FROM Categories LEFT JOIN Posts ON Posts.category_id = Categories.id ORDER BY Categories.id ASC

    ?
    Тогда посты из одной категории будут идти последовательно. Запоминаешь категорию предыдущего поста, при обработке следующего поста сравниваешь. Если не совпадает - закрываешь теги для предыдущей категории, открываешь теги для новой категории.
    Ответ написан
    3 комментария
  • Как выделить значение?

    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 комментариев
  • Можно как-то добавить данные в таблицу без формы?

    Vindicar
    @Vindicar
    RTFM!
    Взять клиент для используемой БД, подключиться к БД, внести нужные исправления?
    Ответ написан
  • Как запускать асинхронную функцию одновременно с поллингом бота телеграмм?

    Vindicar
    @Vindicar
    RTFM!
    start_polling() имеет параметр on_startup, который принимает корутину или список корутин.
    Ответ написан
    Комментировать
  • Не понимаю почему не работает код 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  # заменяем декорируемую функцию на то, что вернул декоратор



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