Задать вопрос
  • Как показывать количество символов в Google Sheets?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Чтобы корректно отрабатывало - разместить формулу в нужной ячейке - G4.
    =ARRAYFORMULA(IF(F4:F=""; ""; LEN(F4:F)))
    Аналогично со второй формулой - в G2.
    =ARRAYFORMULA(IF(LEN(F2:F)>0; LEN(F2:F); ""))
    69c59fde83cc8363200694.png
    Ответ написан
    Комментировать
  • Существуют ли гибридные (наполовину WYSIWYG, наполовину разметка) редакторы Markdown?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Obsidian? Плюс его плагины для таблиц, LaTex, html для расширения WYSIWYG-опыта.
    Ответ написан
    7 комментариев
  • Как запретить удаление полей класса?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Переопределить __delattr__?
    class foo:
        name: str
    
        def __delattr__(self, item):
            if item == "name":
                raise AttributeError(f"Нельзя удалять атрибут: '{item}'")
            #     print('что-то печатаем')
            #     pass  # или ничего не делаем
            super().__delattr__(item)
    
    
    tmp = foo()
    tmp.name = "test"
    try:
        del tmp.name
    except AttributeError as e:
        print(e)
    finally:
        print(tmp.name)


    >>>Нельзя удалять атрибут: 'name'
    >>>test
    Ответ написан
    3 комментария
  • Discord Embed Текст и кнопка в одной строке?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Использовать UI v2 компоненты. В dev версии disnake.py.
    pip uninstall disnake -y
    pip install -U git+https://github.com/DisnakeDev/disnake.git

    Код
    import os
    import disnake
    from disnake.ext import commands
    from disnake import ui
    
    TOKEN = os.environ['TOKEN_DISCORD']
    
    bot = commands.InteractionBot()
    
    @bot.slash_command(name="support", description="Система поддержки")
    async def support(inter: disnake.ApplicationCommandInteraction):
        await inter.response.send_message(
            components=[
                ui.Container(
                    ui.TextDisplay(
                        content=(
                            "## Система поддержки\n"
                            "Выберите тип обращения, а сотрудники нашего сообщества "
                            "своевременно и качественно помогут решить это."
                        )
                    ),
                    ui.TextDisplay(content="### Жалобы"),
                    ui.Section(
                        ui.TextDisplay(content="Жалоба на игрока"),
                        accessory=ui.Button(
                            emoji="",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="complaint_player"
                        )
                    ),
                    ui.Section(
                        ui.TextDisplay(content="Жалоба на персонал"),
                        accessory=ui.Button(
                            emoji="️",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="complaint_staff"
                        )
                    ),
                    ui.Separator(),
                    ui.TextDisplay(content="### Заявки"),
                    ui.Section(
                        ui.TextDisplay(content="Подать апелляцию"),
                        accessory=ui.Button(
                            emoji="",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="appeal"
                        )
                    ),
                    ui.Separator(),
                    ui.TextDisplay(content="### Улучшения"),
                    ui.Section(
                        ui.TextDisplay(content="Сообщить о баге"),
                        accessory=ui.Button(
                            emoji="",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="bug_report"
                        )
                    ),
                    ui.Section(
                        ui.TextDisplay(content="Предложить улучшение"),
                        accessory=ui.Button(
                            emoji="⚙️",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="suggestion"
                        )
                    ),
                    ui.Separator(),
                    ui.TextDisplay(content="### Верификация"),
                    ui.Section(
                        ui.TextDisplay(content="Заявка роль 18+"),
                        accessory=ui.Button(
                            emoji="",
                            style=disnake.ButtonStyle.secondary,
                            custom_id="verify_18"
                        )
                    ),
                    accent_colour=disnake.Colour.from_rgb(249, 134, 106),
                ),
    
                # Select ВСЕГДА ВНЕ Container
                ui.StringSelect(
                    placeholder="❓ Частые вопросы",
                    custom_id="faq_select",
                    options=[
                        disnake.SelectOption(label="Как подать жалобу?", value="faq_complaint"),
                        disnake.SelectOption(label="Сколько рассматривается заявка?", value="faq_time"),
                        disnake.SelectOption(label="Куда отправляются обращения?", value="faq_where"),
                    ]
                )
            ]
        )
    
    
    # ───── Обработчик кнопок ─────
    @bot.listen("on_button_click")
    async def on_button(inter: disnake.MessageInteraction):
        cid = inter.component.custom_id
    
        modal = ui.Modal(
            title="Обращение в поддержку",
            custom_id=f"modal_{cid}",
            components=[
                ui.TextInput(
                    label="Опишите проблему",
                    custom_id="text",
                    style=disnake.TextInputStyle.paragraph,
                    required=True,
                    max_length=1000,
                )
            ],
        )
    
        await inter.response.send_modal(modal)
    
    bot.run(TOKEN)


    P.S. хабр пожрал эмодзи в коде.

    697a7419034c4388382280.png
    697a4dd6c8dcd957275224.png
    Ответ написан
    1 комментарий
  • Почему uv add -r req.txt валится с ошибкой там, где uv pip install -r req.txt работает?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    uv проверяет совместимость для всех возможных версий, pip - для текущей версии Python.
    При проверке для 3.13 находит несостыковку для требуемой numpy>=2.1.0 и текущей numpy 1.26.4.

    Добавить в pyproject.toml ограничения на используемые версии питона:
    requires-python = ">=3.8,<3.13"
    Или создавать сразу с нужной версией:
    uv init myproject --python 3.12
    Ответ написан
  • Почему код с coqui-tts не генерирует речь?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Используйте:
    torch==2.5.1
    torchaudio==2.5.1
    transformers==4.38.2

    Запускал на Debian 13.

    З.Ы. В русском варианте language забыли указать.
    Ответ написан
    1 комментарий
  • Как получить нужное содержимое Xpath, если по родителю получаю список Element такой-то at?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Продолжать парсить те элементы что вам нужны.
    Например, для названий:
    for el in all_product_information:
        print(el.xpath('h3/a/text()')[0])

    A Light in the ...
    Tipping the Velvet
    Soumission

    Или как-то так:
    product_name = tree.xpath('//article[@class="product_pod"]/h3/a/text()')
    product_price = tree.xpath('//div[@class="product_price"]/p/text()[1]')
    product_price = [i for i in product_price if i != '\n    ']
    
    z = zip(product_name, product_price)
    for i in z:
        print(*i)

    A Light in the ... £51.77
    Tipping the Velvet £53.74
    Soumission £50.10
    Ответ написан
    Комментировать
  • Почему urequests выдает ошибку OSError: -40 при get запросе api telegram при этом корректно работает с api openweather?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Могу предположить почему это происходит:
    ESP8266 использует библиотеку axTLS, которая не умеет в ECC.
    No support for Diffie-Hellman (DH) key exchange and Elliptic-curve cryptography (ECC). This means it can’t work with sites which require the use of these features (it works ok with the typical sites that use RSA certificates).
    https://docs.micropython.org/en/latest/esp8266/gen...

    Сервер OpenWeather разрешает понизить до TLS 1.2 с RSA ключом, что позволяет успешно завершить handshake.
    openssl s_client -connect api.openweathermap.org:443 -servername api.openweathermap.org -tls1_2 -cipher RSA


    Сервер Telegram более строг, не разрешает RSA-only и требует ECDHE (X25519) -> sslv3 alert handshake failure
    openssl s_client -connect api.telegram.org:443 -servername api.telegram.org -tls1_2 -cipher RSA

    Как я понимаю, SSL alert number 40 в выводе openssl это и есть ваш OSError: -40.

    1. Переходите на ESP32 там отправка работает корректно.
    2. Ну, или, если 8266 принципиально использовать, то прикручивать прокси: 8266 -> прокси -> telegram. Хендшейк будет делать прокси вместо ESP.
    Для примера:

    Прокси на Flask.
    from flask import Flask, request
    import requests
    
    app = Flask(__name__)
    
    TOKEN = ""
    CHAT_ID = ""
    
    @app.route("/send", methods=["GET"])
    def send_message():
        text = request.args.get("text", "")
        print(text)
        if not text:
            return "No text provided", 400
    
        url = f"https://api.telegram.org/bot{TOKEN}/sendMessage"
        try:
            r = requests.get(url, params={"chat_id": CHAT_ID, "text": text}, timeout=5)
            return r.text
        except requests.RequestException as e:
            return str(e), 500
    
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=5000)

    Скрипт для ESP8266.

    import urequests
    import network
    import time
    
    SSID = ""
    PASSWORD = ""
    PROXY_URL = "http://192.168.0.5:5000/send"  # Ваш IP прокси-сервера в локальной сети
    
    # подключение к Wi-Fi
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(SSID, PASSWORD)
    while not wlan.isconnected():
        time.sleep(0.5)
    print("Connected, IP:", wlan.ifconfig()[0])
    time.sleep(3)
    # отправка сообщения через прокси
    msg = "Привет_из_ESP8266_5000_142589"
    try:
        print(f"{PROXY_URL}?text={msg}")
        response = urequests.get(f"{PROXY_URL}?text={msg}", timeout=10)
        print(response.text)
        response.close()
    except Exception as e:
        print("Error:", e)


    З.Ы. Не забыть открыть порт 5000 (ну или какой вы там будете использовать) для входящих в файерволе.
    3. Вроде есть mbedTLS с поддержкой TLS 1.3. Сам не пробовал, но встречал на гитхабе где-то что соединение на 8266 занимает 7-8 секунд, ибо мощей не хватает ему. link.
    Ответ написан
    3 комментария
  • Почему с помощью функции pd.read_html() с индексом 1 не показывает таблицу?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Потому что для pd.read_html() это одна таблица. В tables лежит два элемента: таблица первого листа и описание.

    Чтобы по листам читать, пишите так:
    import pandas as pd
    
    sheet_id = '1_qOytrSsownwViP6zCzSYD7SHodbcZI7AxiCHS_t-Aq'  # Пример ID
    sheet_name = 'Лист1'  # Название листа
    url = f'https://docs.google.com/spreadsheet/ccc?key={sheet_id}&output=xlsx'
    
    df = pd.read_excel(url, sheet_name=sheet_name)
    print(df.head())
    Ответ написан
  • Как написать bat-скрипт для включения/отключения устройства?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Без devcon:
    @echo off
    
    set "device_id=HID\MSFT0001&COL02\4&3B114B9D&0&0001"
    
    pnputil /enum-devices /instanceid "%device_id%" | findstr /i "Started" >nul
    
    if %errorlevel% equ 0 (
        echo Устройство ВКЛЮЧЕНО. Отключаем...
        pnputil /disable-device "%device_id%" >nul
    ) else (
        echo Устройство ВЫКЛЮЧЕНО. Включаем...
        pnputil /enable-device "%device_id%" >nul
    )
    
    pause
    Ответ написан
    Комментировать
  • Как такое сверстать?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Ответ написан
    Комментировать
  • Не могу разобраться почему не работает код python?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    # pip3 install python-a2s
    import a2s
    address = ("37.230.137.229", 27015)
    print(a2s.info(address))
    Ответ написан
  • Pycharm для старенького мака?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    izma, здесь, как я понимаю, список профессиональных: https://www.jetbrains.com/pycharm/download/other.html

    Конструируете под свои нужды ссылку:
    https://download.jetbrains.com/python/pycharm-<EDITION>-<VERSION>.<ext>

    Например: https://download-cdn.jetbrains.com/python/pycharm-...
    Ответ написан
    2 комментария
  • Баг с окнами windows server 2019. Правая часть окна всегда за пределами экрана. Кто сталкивался?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Эта проблема всегда существовала. "Запредельные" окна, которые не удаётся схватить, перемещаются клавиатурой по Alt + Пробел -> Переместить -> Стрелки.
    Перемещённое на нужное место окно при повторном открытии, как правило, открывается уже нормально.
    Ответ написан
    2 комментария
  • Как парсить фотографии gspread?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Вытаскивать с google drive как xlsx и потрошить содержимое. Обратить внимание на порядок картинок, если их вытаскивать просто механически, то порядок может не соответствовать ожидаемому (если таблица заполнялась не строго последовательно / картинки менялись местами / строки менялись местами).
    import xml.etree.ElementTree as ET
    import zipfile
    
    from google.oauth2.service_account import Credentials
    from googleapiclient.discovery import build
    import pandas as pd
    
    # Настройки:
    CREDENTIALS_FILE = 'GoogleSheetsCredentional.json'
    FILE_ID = '18c2nnuVKZ-ndfklC6x9Sv9e84PFKc'  # из URL таблицы
    SCHEMA = './/{http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing}'
    
    # Аутентификация и скачивание:
    creds = Credentials.from_service_account_file(CREDENTIALS_FILE, scopes=['https://www.googleapis.com/auth/drive'])
    
    drive_service = build('drive', 'v3', credentials=creds)
    
    # Скачиваем как Excel:
    content = drive_service.files().export_media(
        mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', fileId=FILE_ID).execute()
    
    # Сохраняем временный файл:
    with open('temp.xlsx', 'wb') as f:
        f.write(content)
    
    # Извлекаем данные и картинки:
    df = pd.read_excel('temp.xlsx')
    
    with zipfile.ZipFile('temp.xlsx', 'r') as z:
        # Парсим drawing.xml - потому что порядок картинок может быть не тот что ожидается...
        drawing_data = z.read('xl/drawings/drawing1.xml')
        root = ET.fromstring(drawing_data)
        file_names = []
        # Извлекаем картинки:
        for anchor in root.findall(f'{SCHEMA}oneCellAnchor'):
            image_name = anchor.find(f'{SCHEMA}cNvPr').get('name')
            file_names.append(image_name)
            z.extract(f'xl/media/{image_name}', 'images')
    
        df['image'] = pd.Series(file_names)
    print(df)

    68e5e85041844803428218.png

    З.Ы. можно тоже самое сделать на openpyxl и, наверное, даже проще.
    Ответ написан
    Комментировать
  • Xiaomi AX3000T или Cudy WR3000E?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    На текущий момент однозначно Cudy (WR3000E или WR3000S).
    C Xiaomi AX3000T у вас есть отличный от нуля шанс купить роутер ревизии RD03V2 на Qualcomm, на который нет (и вероятно не будет) OpenWRT.

    А так, оба спокойно и легко прошиваются на OpenWRT. Работают стабильно со всеми штуками, ради которых их перепрошивают. Памяти хватает, места хватает. Cudy к тому же не препятствует перепрошивке.
    Ответ написан
    Комментировать
  • Существуют ли сервисы: онлайн python editor для совместного использования?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    JetBrains Fleet?
    С помощью Fleet удобно работать над кодом вместе с коллегами в реальном времени. IDE не только поддерживает совместное редактирование кода, но и позволяет использовать общий терминал, заниматься отладкой и исследованием кода, выполнять код-ревью и многое другое — все это без дополнительной настройки.
    Ответ написан
  • Как связать html-код c python при помощи Flask?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Закрыть блок for в jinja: {% endfor %}.
    Ответ написан
    3 комментария
  • Поиск по образцу. Как сделать быстрый поиск вхождения картинок-символов на большом чертеже?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    import cv2
    import numpy as np
    
    # Загрузка изображений:
    dr_image = cv2.imread('original.png')
    
    # Преобразуем в серое:
    gray = cv2.cvtColor(dr_image, cv2.COLOR_BGR2GRAY)
    
    # Бинаризация: черные линии → белые (на чёрном фоне).
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    
    # Шаблоны:
    template1 = cv2.imread('temp2.png', cv2.IMREAD_GRAYSCALE)  # ёлочка
    template2 = cv2.imread('temp1.png', cv2.IMREAD_GRAYSCALE)  # круг
    
    _, template1 = cv2.threshold(template1, 127, 255, cv2.THRESH_BINARY_INV)
    _, template2 = cv2.threshold(template2, 127, 255, cv2.THRESH_BINARY_INV)
    
    # Параметры:
    threshold1 = 0.7  # для ёлочки
    threshold2 = 0.5  # для круга
    
    # Поиск "ёлочки":
    result1 = cv2.matchTemplate(binary, template1, cv2.TM_CCOEFF_NORMED)
    loc1 = np.where(result1 >= threshold1)
    
    # Поиск "круга":
    result2 = cv2.matchTemplate(binary, template2, cv2.TM_CCOEFF_NORMED)
    loc2 = np.where(result2 >= threshold2)
    
    # Результат:
    result = dr_image.copy()
    detected_boxes = []
    
    # Обработка "ёлочки":
    for pt in zip(*loc1[::-1]):
        x, y = pt
        w, h = template1.shape[1], template1.shape[0]
        box = (x, y, x + w, y + h)
    
        if not any(np.allclose(box, b, atol=10) for b in detected_boxes):
            detected_boxes.append(box)
            cv2.rectangle(result, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
            cv2.putText(result, "Tree", (pt[0], pt[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
    
    # Обработка "круга":
    for pt in zip(*loc2[::-1]):
        x, y = pt
        w, h = template2.shape[1], template2.shape[0]
        box = (x, y, x + w, y + h)
    
        if not any(np.allclose(box, b, atol=10) for b in detected_boxes):
            detected_boxes.append(box)
            cv2.rectangle(result, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 2)
            cv2.putText(result, "Circle", (pt[0], pt[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
    
    # Сохраняем результат:
    cv2.imwrite('result_with_labels.png', result)
    print(f"Найдено объектов: {len(detected_boxes)}")
    
    # Показываем:
    cv2.imshow('Detected', result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    >>> Найдено объектов: 12

    68cd5e8cccadf938039122.png
    Ответ написан
    3 комментария
  • Как запустить команды в Putty после подключения?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Connection -> SSH -> Remote comand -> Ваши команды.
    Ответ написан
    Комментировать