Задать вопрос
  • Как использовать SSH вместо VPN?

    Vindicar
    @Vindicar
    RTFM!
    А конфиг сервера позволяет динамический проброс портов (AllowTcpForwarding yes)? Там обновлений не было? Может, несколько конфигов конфликтуют? Например, в autorized_keys можно прописать no-port-forwarding или restrict.

    Ну и самая идея такая себе. Многие провайдеры шейпят SSH, жёстко ограничивая максимальную скорость - в терминале поработать можно, а как туннель использовать - нет. Так что даже если раньше работало, может перестать в любой момент.
    Ответ написан
    Комментировать
  • Почему Telegram бот не отвечает?

    Vindicar
    @Vindicar
    RTFM!
    Ну тебе же английским по белому написано:
    RuntimeError: This Application was not initialized via `Application.initialize`!

    Нужно перед вызовом application.start() добавить аналогичный вызов initialize().

    И да, ты пытаешься трогать элементы управления своего окна из другого потока. Так нельзя.
    Ответ написан
    Комментировать
  • Как в numpy максимально быстро изменить структуру данных в массиве?

    Vindicar
    @Vindicar
    RTFM!
    CUDA тут не нужна, просто не следует перебирать массив numpy питоновскими циклами.
    Если есть возможность - выражай желаемое через операции над массивом в целом. Тогда цикл организует numpy, и он это делает через нативный код, ЕМНИП - работает в разы быстрее.
    Подход ниже сожрёт больше памяти, но зато короткий, выразительный и использует только средства numpy.
    image = cv2.imread("image.png")
    image = image.astype(numpy.uint32)  # смена типа нужна, иначе при сдвиге потеряются разряды
    image_clone = (image[..., 0] << 16) | (image[..., 1] << 8) | image[..., 2]

    Если хочется заморочиться по памяти:
    image = cv2.imread("image.png")
    image_clone = numpy.zeros(image.shape[:2], numpy.uint32)
    # краткие формы операций не создают новый массив, а изменяют существующий по месту
    image_clone |= image[..., 0]
    image_clone <<= 8
    image_clone |= image[..., 1]
    image_clone <<= 8
    image_clone |= image[..., 2]


    P.S.: как там, у imread() починили уже неумение работать с юникодными путями?
    Ответ написан
    Комментировать
  • Как сделать чтобы дискорд бот сидел с телефона?

    Vindicar
    @Vindicar
    RTFM!
    Такой механизм не предусмотрен библиотекой. Быстрый гугл по discord.py phone status показывает, что для этого приходится патчить код класса discord.gateway.DiscordWebSoсket, чтобы при отправке пакета identify устройство/клиент идентифицировалось как 'Discord Android'.
    В связи с этим вопрос: тебе оно вот прямо нужно? Или это просто понты?
    Мненада!11

    Более-менее вменяемым (в плане риска что-то сломать при обновлении библиотеки) мне показался такой вариант со стэковерфлоу.
    from discord.gateway import DiscordWebSocket
    
    
    class MyDiscordWebSocket(DiscordWebSocket):
        async def send_as_json(self, data):
            if data.get('op') == self.IDENTIFY:
                if data.get('d', {}).get('properties', {}).get('$browser') is not None:
                    data['d']['properties']['$browser'] = 'Discord Android'
                    data['d']['properties']['$device'] = 'Discord Android'
            return await super().send_as_json(data)
    
    
    DiscordWebSocket.from_client = MyDiscordWebSocket.from_client

    Пробуй на свой страх и риск.


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

    Vindicar
    @Vindicar
    RTFM!
    Открываем официальные примеры, находим простейший эхобот, и начинаем с него.
    В частности, смотрим, каким методом запускается работа бота.
    Спойлер
    bot.infinity_polling()
    Ответ написан
    Комментировать
  • Бот для уведомлений с ютуба не работает больше 3х дней, где я мог ошибиться?

    Vindicar
    @Vindicar
    RTFM!
    Во-первых, научись регистрировать проблемы. Почитай про logging, как его настраивать. Расставь в боте и в парсере try-except и записывай в лог возникающие ошибки. Тогда у тебя будет текст ошибки, с которым уже можно как-то работать.

    Но я подозреваю, что дело в доступе к базе Sqlite из двух процессов. Sqlite, в отличие от "взрослых" БД, не является ни процессо-, ни даже потоко-безопасной. К ней можно безопасно обращаться только строго по очереди.
    Как только звёзды сойдутся так, что оба твоих процесса обращаются к базе одновременно - кому-то из них не повезёт. Если не повезёт парсеру, ты просто не увидишь инфу о новом видео при этом запуске. Если не повезёт боту - бот упадёт.

    Тут вопрос такой: а нужна ли вообще тут БД? Если да, то для чего она нужна?
    yt-dlp, к сожалению, синхронный - но ты ведь можешь выполнять этот код через run_in_executor(). Тогда получится интегрировать парсер прямо в бот, и отправлять сообщения немедленно.

    Альтернативно, можно схитрить так: сделать боту учётку на ютубе, подписать его на нужные каналы и настроить уведомления о новых видео по почте, а в боте мониторить почтовый ящик через email-monitor или подобное.
    Ответ написан
    Комментировать
  • Если у человека нет определённой роли, как сделать так, чтобы другие определённые роли в таком случае отнимались?

    Vindicar
    @Vindicar
    RTFM!
    При снятии реакции снимать все последующие роли. Для этого обработчик события должен знать, какие роли последующие для какой реакции. Т.е. ты должен как-то это прописать.
    Ответ написан
    2 комментария
  • Зачем вообще нужна библиотека python turtle в реальной практике?

    Vindicar
    @Vindicar
    RTFM!
    Обучение. Многие языки для школьников основаны на принципе "черепашки". Сам начинал с LogoWriter и L-Graph, но есть и другие.
    А тут сразу можно привыкнуть к синтаксису питона, заодно.
    Ответ написан
    Комментировать
  • Как сделать кнопку в discord.py БЕЗ класса Client?

    Vindicar
    @Vindicar
    RTFM!
    Класс Bot - потомок класса Client, и может всё то же, что и Client.
    Bot в доках
    Represents a Discord bot.

    This class is a subclass of discord.Client and as a result anything that you can do with a discord.Client you can do with this bot.
    Ответ написан
  • Почему не получается закрыть окно в PyQt5?

    Vindicar
    @Vindicar
    RTFM!
    Ну у твоего класса действительно есть только метод setupUi(), и нет метода close(). Неудивительно, что Питон этот метод тоже не находит.
    Я с Qt не знаком, поэтому поинтересуюсь: а MyMindow точно должно наследоваться от object? Может, от какого другого класса?

    А вообще выглядит всё так, словно этому коду место в MainWindow.
    Ответ написан
    Комментировать
  • Как получить данные с сайта росреестра?

    Vindicar
    @Vindicar
    RTFM!
    Правило номер ноль при парсинге: при любых проблемах сохраняй на диск то, что тебе пришло в ответе от сервера.
    То, что ты видишь в браузере - это не обязательно то же самое, что браузер получил от сайта.
    То, что браузер получил от сайта - это не обязательно то же самое, что requests получит от сайта.

    В данном случае, и requests и браузер получают в ответе вот это:
    <body style="height: 100%; width:100%;">
    <div id=app style="height: 100%; width:100%;"></div>
    <script src=js/chunk-vendors.c1d200da.js></script>
    <script src=js/chunk-common.adcda62e.js></script>
    <script src=js/chunk-esri.caf28189.js></script>
    <script src=js/index.ca134891.js></script>
    </body>

    Как видишь, нужного элемента тут просто нет, потому что он создаётся динамически, через JavaScript. А BS не выполняет скрипты.

    Варианта только два:
    1. Выяснять, каким запросом сайт подтягивает данные для этого, научиться этот запрос делать самостоятельно и вытаскивать искомые данные из полученного. Медленно и трудно на подготовительном этапе, зато потом работает сравнительно быстро... если, конечно, сайт защиту от парсинга не поставит.
    2. Запускать управляемый браузер, дать ему загрузить страницу и выполнить скрипты, а потом уже искать нужные данные. Быстрое решение в плане разработки, но более медленное и ресурсоёмкое в дальнейшем использовании.
    Ответ написан
    Комментировать
  • Как отрыть ссылку с помощью flet с регистром?

    Vindicar
    @Vindicar
    RTFM!
    Твоя ссылка парсится так:
    1. nullsbrawl - схема
    2. createAndJoinRoom - адрес узла, точнее, доменное имя. Доменные имена не имеют регистра, насколько я знаю, т.е. habr.com и HABR.COM - одно и то же имя. Вероятно, поэтому оно и преобразуется в нижний регистр.
    3. пустой путь к ресурсу - подразумевается корневой ресурс
    4. всё, что после ? - параметры запроса

    Ты можешь попробовать изменить ссылку так: nullsbrawl:///createAndJoinRoom?....
    Обрати внимание на дополнительный слэш. Эта ссылка парсится так:
    1. nullsbrawl - схема
    2. адрес узла пустой
    3. createAndJoinRoom - путь к ресурсу на указанном узле. Пути регистрозависимы в URL, а потому его трогать не будут.
    4. всё, что после ? - параметры запроса
    Ответ написан
  • Почему питоновский скрипт сам по себе рабочий, а в виде службы - нет?

    Vindicar
    @Vindicar
    RTFM!
    Виртуальное окружение в проекте есть? Если да, то запускать скрипт надо не системным питоном, а питоном из этого окружения.
    EDIT1:
    Если из командной строки дать pyhon3 /home/lxm213/script.py, то скрипт работает штатно и без ошибок

    Т.е. скрипт запускаешь в системном окружении, а не в виртуальном. ОК, тогда по идее он должен работать...
    Но встаёт вопрос: как ты ставил schedule? Просто pip install schedule? Из-под рута ставил или с правами просто пользователя?
    Если ставил из-под рута, то библиотека будет установлена в системный интерпретатор и будет доступна всем пользователям.
    Если ставил не из-под рута, то, возможно, pip поставил её куда-то в твой домашний каталог - я знаю, что под виндой он так делает. Тогда библиотека доступна только если запускать скрипт из-под твоего пользователя.

    Отсюда три возможных решения:
    1. Создать виртуальное окружение для проекта, поставить библиотеку в это виртуальное окружение (используя местный pip), запускать скрипт через python3 из этого окружения.
    2. Если библиотека была поставлена без рут-прав, указать в .service-файле, что скрипт надо запускать от имени твоего пользователя, а не от имени root.
    3. Убедиться, что библиотека поставлена в системный интерпретатор. При необходимости поставить её с рут-правами. Тогда скрипт будет работать из-под любого пользователя.
    Ответ написан
    9 комментариев
  • Aiogram3.8.0 Как можно сделать команды, которые будут без префикса не используя startwith?

    Vindicar
    @Vindicar
    RTFM!
    # с пробелом - параметры, без пробела просто совпадение.
    if message.text.startswith('command' + ' ') or message.text == 'command':
        ...

    Ну и разумеется, это надо проверять не деревом if-elif-else, а чем-то более вменяемым, чтобы можно было сразу параметры разбирать.
    Ответ написан
    Комментировать
  • Обработка params ?fields в апи запросе для вывода в response?

    Vindicar
    @Vindicar
    RTFM!
    Рекурсивно делай. Опиши требуемую функцию:
    def filter_fields(obj: dict[str, ...], fields: list[str]) -> dict[str, ...]:
        """obj - фильтруемый словарь, fields - множество полей, которые надо оставить."""
        ...

    Проблема в том, что поля могут быть вложенным. Тогда первым делом составляешь набор нужных тебе полей верхнего уровня:
    top_level_fields = {}
    for f in fields:
        top, _, bottom = f.partition('.')
        top_level_fields.setdefault(top, [])
        if bottom is not None:
            top_level_fields[top].append(bottom)

    Для
    fields=['boardId', 'name', 'Data.Matches.t.id', 'Data.Matches.m']
    в top_level_fields получишь
    { 'boardId': [], 'name': [], 'Data': ['Matches.t.id', 'Matches.m']}

    Дальше перебираешь поля, собираешь их значения в один мешок и смотришь, есть ли для них нижележащие поля:
    output = {}
    for top, bottom in top_level_fields.items():
        if bottom:
            output[top] = filter_fields(obj[top], bottom)  # что делать, если ключа top нет?
        else:
            output[top] = obj[top]

    Таким образом наберёшь всё, что надо.
    Ответ написан
    Комментировать
  • Как получить содержимое сообщения до его редактирования в discord через requests?

    Vindicar
    @Vindicar
    RTFM!
    Насколько я знаю - никак. Ты можешь ловить событие редактирования сообщения - тогда ты получишь старую и новую версии. Но и только.
    Ответ написан
  • Сообщения отправляются одному человеку хотя должный двум, как сделать так чтобы сообщения отправлялись 2 пользователям?

    Vindicar
    @Vindicar
    RTFM!
    Проверь, не одинаковые ли значения в user_id и poroh.
    Если так, проверяй, откуда берётся значение user_id.

    EDIT: Когда ты нажимаешь на "Да", это отдельное сообщение - отправленное от тебя!
    Т.е. server() вызывается дважды, один раз для запустившего (после выбора карты), второй раз для тебя (ответ да или нет). Это, к слову, несёт в себе ещё одну проблему - если два человека попросят запустить сервер одноврнменно, боту будет тяжело понять, на чей запрос ты ответил.
    Тебе надо использовать не ReplyKeyboardMarkup, а InlineKeyboardMarkup, так как там можно привязать к кнопке дополнительную инфу (строку), по которой бот сможет потом понять, к какому сообщению относилась кнопка.
    Ответ написан
  • Где найти ошибку в коде?

    Vindicar
    @Vindicar
    RTFM!
    Почитай про импорты в питоне, какой-нибудь толковый учебник (типа Лутца).
    Ты делаешь относительный импорт (import .something), но это можно использовать только в крупных модулях проекта, а не в корневых файлах. Импортируй как обычно, без точки.
    Ответ написан
    Комментировать
  • Взаимодействие методов внутри класса?

    Vindicar
    @Vindicar
    RTFM!
    # Ты заявляешь следущее:
    # "метод udar должен вызываться на экземпляре объекта (self) с двумя параметрами: hp и dmg"
    def udar(self,hp,dmg):
        print("Наносит урон с руки")
        # при этом метод не использует переданные параметры?
        rep = self.hp - self.dmg  # почему self.dmg? Боец бьёт себя?
        return "Осталось здоровья: " + rep
    
    
    # а ниже у тебя:
    # метод udar() фактически вызывается с одним параметром: другим бойцом
    boec.udar(boec2)


    Твоя проблема та же, что и всех новичков: ты не озаботился сформулировать обязанности метода, что должен делать это метод с точки зрения решаемой программой задачи.
    Например, сейчас у тебя путаница: метод имитирует нанесение удара бойцом self по бойцу, переданному как параметр? Или же наоборот, удар бойцом, переданным как параметр, по бойцу self? И уж точно не нужно прикручивать сюда ещё и вывод текста в консоль, это посторонняя обязанность, не относящаяся к классу бойца.

    Вот моя идея (может, несколько усложнённая, но, надеюсь, понятная):
    class Fighter:
        def __init__(self, name: str, hp: int, damage: int):  # указывай типы параметров - так проще понять, что нужно методу
            """Конструктор инициализирует экземпляр бойца заданными значениями."""
            self.name: str = name
            self.hp: int = hp
            self.damage: int = damage
        
        def is_defeated(self) -> bool:
            """Возвращает True, если боец не может более сражаться."""
            return self.hp <= 0  # в простейшем случае, если у бойца не осталось HP
    
        def calculate_attack_on(self, other: 'Fighter') -> int:
            """Метод определяет, сколько урона наш боец (self) нанесёт бойцу other. Возвращает число очков урона."""
            # сейчас урон всегда одинаков, но потом тут можно будет прикрутить что-то посложнее
            # например, рандомный урон в диапазоне, или бонусы/малусы против конкретных бойцов, или ещё что
            return self.damage  
    
        def receive_damage(self, damage: int) -> int:
            """Метод определяет, сколько HP наш боец (self) потеряет, получив урон damage, и уменьшает его здоровье. Возвращает число фактически потерянных очков здоровья."""
            # сейчас метод просто вычитает урон из очков здоровья. 
            # но потом при желании можно добавить, например, механику "последний шанс", 
            # когда первый "смертельный" удар оставляет бойца на 1 хп. Или сопротивление/уязвимость к урону, или ещё что.
            lost = min(self.hp, damage)  # если у нас 1 очко здоровья, мы не можем потерять 10
            self.hp -= lost
            return lost
    
        def attack_other(self, target: 'Fighter') -> int:
            """Проводит атаку нашего бойца (self) по другому бойцу (target). Возвращает нанесённый урон."""
            attack_damage = self.calculate_attack_on(target)
            actual_damage = target.receive_damage(attack_damage)
            return actual_damage

    Как видишь, у каждого метода есть свой достаточно чётко очерченный круг обязанностей. Хотя, конечно, можно придраться и сказать, что receive_damage() делает две вещи и его стоит разбить на два метода.
    Названия методов должны однозначно указывать, что они делают. Например, udar ничего не говорит о том, кто кого ударяет, тогда как attack_other намекает, что атаку производит тот, у кого вызвали метод, в адрес того, кого передали как параметр метода. То же самое касается параметров методов.
    Весь вывод вынесен из класса, это не его обязанность:
    boec = Fighter("вася",200,22)
    boec2 = Fighter("bob",100,19)
    print(f'{boec.name}: {boec.hp} HP;  {boec2.name}: {boec2.hp} HP')
    dmg = boec.attach_other(boec2)
    print(f'{boec.name} нанёс {dmg} урона {boec2.name}')
    print(f'{boec.name}: {boec.hp} HP;  {boec2.name}: {boec2.hp} HP')
    Ответ написан
    2 комментария
  • Как ускорить запуск .exe файла?

    Vindicar
    @Vindicar
    RTFM!
    Если проблема именно в "юзер сбит с толку", то её можно обойти, а не решить. Я, например, когда писал гуишную программу, завязанную на numpy, scipy и matplotlib, в итоге плюнул и сделал простой splash screen, который показывается при загрузке и пред-импортирует требуемые модули, показывая прогрессбар. А у pyinstaller есть опция --splash, которая будет показывать прогресс распаковки.

    А так - профилируй приложение, выясняй, на чём задержка. Добавь отладочный вывод в самое начало скрипта, до импортов, чтобы понять, идёт ли задержка на этапе запуска интерпретатора, или на этапе ипорта модулей.
    Ответ написан
    Комментировать