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

    @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 комментария
  • Почему 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 комментария
  • Не могу разобраться почему не работает код python?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    # pip3 install python-a2s
    import a2s
    address = ("37.230.137.229", 27015)
    print(a2s.info(address))
    Ответ написан
  • Как парсить фотографии 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 и, наверное, даже проще.
    Ответ написан
    Комментировать
  • Существуют ли сервисы: онлайн python editor для совместного использования?

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

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Если исходить из условия, то вам достаточно:
    url = 'test.com/dir1/dir2/dir3/page.html'
    page_name = url.split('/')[-1]
    print(page_name)
    >>>page.html

    И зачем нужен остальной код непонятно.
    Ответ написан
    2 комментария
  • Возможность использования анонимного адреса @MAIL.RU для скрипта рассылки?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    import smtplib
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
    
    
    def send_email_mail_ru():
        smtp_server = "smtp.mail.ru"
        smtp_port = 587  # или 465 для SSL.
        username = "*****@mail.ru" # Анонимный ящик.
        password = "****************"  # Пароль от приложения.
    
        # Создаем сообщение:
        msg = MIMEMultipart()
        msg['From'] = username
        msg['To'] = "************@mail.ru"
        msg['Subject'] = "Тестовое письмо с Mail.ru"
    
        # Текст письма:
        body = """тест"""
        msg.attach(MIMEText(body, 'plain', 'utf-8'))
    
        try:
            # Подключаемся к серверу:
            server = smtplib.SMTP(smtp_server, smtp_port)
            server.starttls()
            server.login(username, password)
    
            # Отправляем письмо:
            server.sendmail(username, "*********@yahoo.com", msg.as_string())
            print("Письмо успешно отправлено через Mail.ru!")
    
        except Exception as e:
            print(f"Ошибка при отправке: {e}")
        finally:
            server.quit()
    
    send_email_mail_ru()
    Ответ написан
    8 комментариев
  • Как правильно сформировать запрос Python requests?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Скорее всего requests детектят по фингерпринту. pyOpenSSL + cryptography меняют TLS-стек:
    pip install pyOpenSSL cryptography idna certifi urllib3[secure] requests[security]


    import urllib3.contrib.pyopenssl  # активирует pyOpenSSL для urllib3
    urllib3.contrib.pyopenssl.inject_into_urllib3()
    
    import requests
    
    url = "https://www.wildberries.ru/webapi/product/339182812/data?subject=104&kind=1&brand=311487279&lang=ru"
    
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
        "Accept": "*/*",
        "Referer": "https://www.wildberries.ru/catalog/339182812/detail.aspx",
        "X-Requested-With": "XMLHttpRequest",
    }
    
    response = requests.get(url, headers=headers)
    print(response.status_code)
    print(response.text)


    >>>200
    >>>{"resultState":0,"value":{"data":{"brandAndSubjectUrl":"/brands/311...


    З.Ы. можно вообще без headers, потому что дело не в них.
    Ответ написан
    1 комментарий
  • Как создать параметризированный SQL запрос через pyodbc к Mysql?

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

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Unandoriz,
    1. В секции инициализации перенести self.load_config() в самый конец:
    def __init__(self, window_title=None):
            ...
            self.load_config()

    2. Создать экземпляр, запустить главный цикл:
    # Ваш код
    if __name__ == "__main__":
        app = AutoKeylogger(window_title="Notepad++")  # Укажите нужное название окна.
        app.root.mainloop()


    З.Ы. Это если вам интересно запустить просто. Работать как вы хотите оно не будет, имхо.
    Ответ написан
    Комментировать
  • Почему у меня программа вообще не реагирует на свойства в python?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Разве IDE не подчёркивает вам проблемные места?

    Вы не вызываете конструктор родительского класса:
    class Villains(Heroes):
        def __init__(self):
            super().__init__()


    И не очень понятно когда проблема проявляется, при инициализации переменных? Но вы не проверяете никак __hp и __damage. А там, где есть логика проверки, надо понимать что __damage != new_damage и __hp != new_hp.

    После инициализации всё корректно, имхо, работает:
    688e808ad1739508277546.png
    Ответ написан
  • Как распарсить смешанный тип json-данных?

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

    Если точно известно что там всё есть, то обращаться напрямую:
    parsed_data = json.loads(json_data)
    ip_address = parsed_data["data"]["ipAddress"]


    Если могут быть сюрпризы, то:
    ip_address = parsed_data.get("data", {}).get("ipAddress", "N/A")

    import json
    
    json_data = '''
    {
      "data": {
        "ipAddress": "192.168.1.1",
        "abuseConfidenceScore": 85
      }
    }
    '''
    parsed_data = json.loads(json_data)
    try:
        ip_address = parsed_data.get("data", {}).get("ipAddress", "N/A")
        score = parsed_data.get("data", {}).get("abuseConfidenceScore", 0)
        print(f"IP: {ip_address}, Score: {score}")
    except Exception as e:
        print(f"Ошибка: {e}")
    Ответ написан
    Комментировать
  • Почему не получается создать профиль в программе Dolphin{anty}?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    У меня так сработало:
    import requests
    
    token = '...'
    headers = {
        "Authorization": f"Bearer {token}",
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    
    # Обязательные параметры (заполните своими значениями):
    name = "lol"  # Обязательное поле
    platform = "windows"  # Обязательное поле (например: "windows", "mac", "linux")
    browser_type = "anty"  # Обязательное поле (например: "chrome", "firefox", "anty")
    proxy_type = "http"
    proxy_host = "None" # Тут тоже что-то своё надо, видимо, вставлять.
    useragent_mode = "manual"
    useragent_value = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    
    # Остальные параметры (можно оставить пустыми или заполнить по необходимости):
    tags = []
    tabs = ""
    main_website = ""
    webrtc_mode = ""
    webrtc_ip_address = ""
    canvas_mode = ""
    webgl_mode = ""
    webgl_info_mode = ""
    webgl_info_vendor = ""
    webgl_info_renderer = ""
    # Заменить webgl2Maximum на ваше. Это всего лишь пример:
    webgl_info_webgl2_maximum = r'{\"MAX_SAMPLES\": 8, \"MAX_DRAW_BUFFERS\": 8, \"MAX_TEXTURE_SIZE\": 16384, \"MAX_ELEMENT_INDEX\": 4294967294, \"MAX_VIEWPORT_DIMS\": [16384, 16384], \"MAX_VERTEX_ATTRIBS\": 16, \"MAX_3D_TEXTURE_SIZE\": 2048, \"MAX_VARYING_VECTORS\": 30, \"MAX_ELEMENTS_INDICES\": 2147483647, \"MAX_TEXTURE_LOD_BIAS\": 15, \"MAX_COLOR_ATTACHMENTS\": 8, \"MAX_ELEMENTS_VERTICES\": 2147483647, \"MAX_RENDERBUFFER_SIZE\": 16384, \"MAX_UNIFORM_BLOCK_SIZE\": 65536, \"MAX_VARYING_COMPONENTS\": 120, \"MAX_TEXTURE_IMAGE_UNITS\": 32, \"MAX_ARRAY_TEXTURE_LAYERS\": 2048, \"MAX_PROGRAM_TEXEL_OFFSET\": 7, \"MIN_PROGRAM_TEXEL_OFFSET\": -8, \"MAX_CUBE_MAP_TEXTURE_SIZE\": 16384, \"MAX_VERTEX_UNIFORM_BLOCKS\": 13, \"MAX_VERTEX_UNIFORM_VECTORS\": 4096, \"MAX_COMBINED_UNIFORM_BLOCKS\": 60, \"MAX_FRAGMENT_UNIFORM_BLOCKS\": 13, \"MAX_UNIFORM_BUFFER_BINDINGS\": 72, \"MAX_FRAGMENT_UNIFORM_VECTORS\": 4096, \"MAX_VERTEX_OUTPUT_COMPONENTS\": 124, \"MAX_FRAGMENT_INPUT_COMPONENTS\": 124, \"MAX_VERTEX_UNIFORM_COMPONENTS\": 16384, \"MAX_VERTEX_TEXTURE_IMAGE_UNITS\": 32, \"MAX_FRAGMENT_UNIFORM_COMPONENTS\": 16384, \"UNIFORM_BUFFER_OFFSET_ALIGNMENT\": 256, \"MAX_COMBINED_TEXTURE_IMAGE_UNITS\": 64, \"MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS\": 229376, \"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS\": 4, \"MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS\": 229376, \"MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS\": 4, \"MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS\": 128}'
    notes_icon = ""
    notes_color = ""
    notes_style = ""
    notes_content = ""
    timezone_mode = ""
    timezone_value = ""
    locale_mode = ""
    locale_value = ""
    status_id = ""
    geolocation_mode = ""
    geolocation_latitude = ""
    geolocation_longitude = ""
    cpu_mode = ""
    cpu_value = ""
    memory_mode = ""
    memory_value = ""
    do_not_track = ""
    proxy_id = ""
    
    proxy_port = ""
    proxy_login = ""
    proxy_password = ""
    proxy_name = ""
    proxy_change_ip_url = ""
    
    # F-строка
    payload = f'name={name}&tags%5B%5D={tags}&tabs={tabs}&platform={platform}&mainWebsite={main_website}&useragent%5Bmode%5D={useragent_mode}&useragent%5Bvalue%5D={useragent_value}&webrtc%5Bmode%5D={webrtc_mode}&webrtc%5BipAddress%5D={webrtc_ip_address}&canvas%5Bmode%5D={canvas_mode}&webgl%5Bmode%5D={webgl_mode}&webglInfo%5Bmode%5D={webgl_info_mode}&webglInfo%5Bvendor%5D={webgl_info_vendor}&webglInfo%5Brenderer%5D={webgl_info_renderer}&webglInfo%5Bwebgl2Maximum%5D={webgl_info_webgl2_maximum}&webrtc%3A%20%7Bmode%3A%20%22altered%22%2C%20ipAddress%3A%20null%7D&notes%5Bicon%5D={notes_icon}&notes%5Bcolor%5D={notes_color}&notes%5Bstyle%5D={notes_style}&notes%5Bcontent%5D={notes_content}&timezone%5Bmode%5D={timezone_mode}&timezone%5Bvalue%5D={timezone_value}&locale%5Bmode%5D={locale_mode}&locale%5Bvalue%5D={locale_value}&statusId={status_id}&geolocation%5Bmode%5D={geolocation_mode}&geolocation%5Blatitude%5D={geolocation_latitude}&geolocation%5Blongitude%5D={geolocation_longitude}&cpu%5Bmode%5D={cpu_mode}&cpu%5Bvalue%5D={cpu_value}&memory%5Bmode%5D={memory_mode}&memory%5Bvalue%5D={memory_value}&doNotTrack={do_not_track}&browserType={browser_type}&proxy%5Bid%5D={proxy_id}&proxy%5Btype%5D={proxy_type}&proxy%5Bhost%5D={proxy_host}&proxy%5Bport%5D={proxy_port}&proxy%5Blogin%5D={proxy_login}&proxy%5Bpassword%5D={proxy_password}&proxy%5Bname%5D={proxy_name}&proxy%5BchangeIpUrl%5D={proxy_change_ip_url}'
    
    url = "https://dolphin-anty-api.com/browser_profiles"
    response = requests.request("POST", url, headers=headers, data=payload)
    print(response.json())

    68821a5c5cb3a524599248.png

    В сам Dolphin{anty} профиль тоже подсосался после рефреша:
    68821b2fe0493862243582.png
    Ответ написан
    Комментировать
  • Какова временная сложность del[pos:] для списка в Python?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Сложность O(n).
    Если делать замеры для списков разных размеров, то увидим что время выполнения растёт линейно, что подтверждает сложность O(n).

    Если же сложность не O(1), то почему? Ведь перемещать ничего не надо.
    Удаление среза реализовано как проход по удаляемым элементам с вызовом Py_DECREF на каждый.

    З.Ы. чисто теоретически сложность O(1) может быть для крайнего случая с pos = 0, если целиком уничтожается вся структура (но так ли это в реальности надо проверять) и pos = n - 1.
    Ну и надо разделять абстрактную алгоритмику и конкретные бенчмарки.

    6867dce1a31c0265426845.png

    Код.
    import time
    import matplotlib.pyplot as plt
    
    
    def test_del_slice_complexity():
        sizes = [10 ** 3, 10 ** 4, 10 ** 5, 10 ** 6]
        times = []
    
        for n in sizes:
            # Создаем список
            my_list = [1] * n
    
            # Замеряем время удаления
            start_time = time.perf_counter()
            del my_list[n // 2:]  # Удаляем 50% элементов
            end_time = time.perf_counter()
    
            elapsed = end_time - start_time
            times.append(elapsed)
    
            print(f"n = {n:>7}: {elapsed:.6f} сек")
    
        # Визуализация результатов
        plt.figure(figsize=(10, 5))
        plt.plot(sizes, times, 'o-', label='Измеренное время')
        plt.plot(sizes, [times[0] * n / sizes[0] for n in sizes], '--', label='Ожидаемое линейное время')
        plt.xscale('log')
        plt.yscale('log')
        plt.xlabel('Размер списка (n)')
        plt.ylabel('Время выполнения (сек)')
        plt.title('Сложность операции del my_list[n//2:]')
        plt.legend()
        plt.grid(True)
        plt.show()
    
    
    if __name__ == "__main__":
        test_del_slice_complexity()
    Ответ написан
    4 комментария
  • Из-за ошибки текстовый файлик занимает всё свободное место на носителе, как это исправить?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Используйте loggingс ограничением размера лога параметром maxBytes, чтобы не изобретать велосипед.

    я включаю символ "\n" в функции get_nmea_datetime

    Где?
    Вы накапливаете данные в data, при появлении перевода строки записываете их. Но не добавляете '\n'.

    Ну и, вероятно, могут не выполняться условия выше data=''и оно может не обнуляться.

    З.Ы. ну и в целом: работайте с файлами через контекстный менеджер with, добавьте логирование и обработку исключений (для себя прежде всего), аннотации и комментарии к коду (для других), тем более, если он будет опубликован.
    Ответ написан
    2 комментария
  • Как исправить игнорирование кода при импорте в python?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    Используйте коги: https://discordpy.readthedocs.io/en/stable/ext/com...

    main.py:
    import discord
    from discord.ext import commands
    
    intents = discord.Intents.default()
    intents.message_content = True
    
    bot = commands.Bot(command_prefix="!", intents=intents)
    
    async def load_extensions():
        await bot.load_extension("ticket")  # Загружаем Cog без .py
    
    @bot.event
    async def on_ready():
        print(f"Бот {bot.user} готов!")
        await load_extensions()
    
    bot.run("***")


    ticket.py:
    from discord.ext import commands
    
    class TicketsCog(commands.Cog):
        def __init__(self, bot):
            self.bot = bot
    
        @commands.command(name="systicket")
        async def systicket(self, ctx):
            """Обработка команды !systicket"""
            # логика команды
            await ctx.send("Система тикетов работает!")  # Пример ответа
    
    async def setup(bot):
        await bot.add_cog(TicketsCog(bot))  # Важно: await и новое API discord.py 2.0+
    Ответ написан
    Комментировать
  • Как создать/изменить примечание (Note) в Google.Sheets.API?

    @dim5x
    ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
    from googleapiclient.discovery import build
    from google.oauth2 import service_account
    
    # Укажите путь к скачанному JSON-файлу сервисного аккаунта
    SERVICE_ACCOUNT_FILE = 'ваш_сервис_аккаунт_файл.json'
    
    # Настройка доступа
    credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE,
        scopes=['https://www.googleapis.com/auth/spreadsheets'])
    
    service = build('sheets', 'v4', credentials=credentials)
    
    def update_note(spreadsheet_id, sheet_name, cell, note_text):
        # Конвертация имени ячейки в индексы:
        col = ord(cell[0].upper()) - ord('A')
        row = int(cell[1:]) - 1
    
        # Получаем ИД листа:
        spreadsheet = service.spreadsheets().get(
            spreadsheetId=spreadsheet_id,
            fields="sheets(properties(sheetId,title))"
        ).execute()
    
        sheetId = [sheet['properties']['sheetId'] for sheet in spreadsheet['sheets'] if
                   sheet['properties']['title'] == sheet_name][0]
        print(sheetId)
    
        service.spreadsheets().batchUpdate(
            spreadsheetId=spreadsheet_id,
            body={
                "requests": [{
                    "updateCells": {
                        "range": {
                            "sheetId": sheetId,
                            "startRowIndex": row,
                            #"endRowIndex": row + 1,
                            "startColumnIndex": col,
                            #"endColumnIndex": col + 1
                        },
                        "rows": [{"values": [{"note": note_text}]}],
                        "fields": "note"
                    }
                }]
            }
        ).execute()
    
    
    # Использование:
    spreadsheetId = 'ваш ид таблицы'
    update_note(spreadsheetId, "Лист3", "B3", "Тестовое примечание.")


    З.Ы. Для "сложных" ячеек ("AA15" итд.), если у вас такие есть, перепишите конвертацию имени ячейки в индексы, текущая работать не будет корректно.

    Чтение примечания с ячейки:
    def read_note(spreadsheet_id, sheet_name, cell) -> str or None:
        response = service.spreadsheets().get(
            spreadsheetId=spreadsheet_id,
            ranges=[f"{sheet_name}!{cell}"],
            fields='sheets(data.rowData.values.note)'
        ).execute()
    
        note = (response
                .get('sheets', [{}])[0]
                .get('data', [{}])[0]
                .get('rowData', [{}])[0]
                .get('values', [{}])[0]
                .get('note'))
    
        return note
    
    # Использование:
    spreadsheetId = 'ваш ид таблицы'
    read_note(spreadsheetId, 'Лист3', 'B3')
    Ответ написан
    1 комментарий