Сообщество - Программирование на python

Программирование на python

945 постов 11 952 подписчика

Популярные теги в сообществе:

4

Добавление, удаление и очистка абзацев в документах Word с помощью Python

Добавление, удаление и очистка абзацев в документах Word с помощью Python

Работа с документами Word программно является распространённой задачей в сценариях автоматизации документов, таких как генерация отчетов, обработка шаблонов и очистка контента. Одной из самых частых задач является добавление, удаление или очистка абзацев.

В этой статье вы узнаете, как добавлять и удалять абзацы в документе Word с помощью Python, с практическими примерами, основанными на Spire.Doc для Python.

Содержание

  • Что такое Spire.Doc для Python

  • Установка необходимой библиотеки

  • Добавление абзаца

  • Удаление абзаца

  • Удаление пустых/незаполненных абзацев

  • Заключительные мысли

Что такое Spire.Doc для Python

Spire.Doc для Python — это библиотека для обработки документов Word, которая позволяет разработчикам создавать, редактировать и манипулировать файлами DOC и DOCX программно — без необходимости в Microsoft Word.

Она предлагает обширные API для работы с абзацами, стилями, таблицами и общей структурой документа, что делает её практичным выбором для задач автоматизации и обработки документов Word в Python.

Установка необходимой библиотеки

Перед началом работы установите Spire.Doc для Python с помощью pip:

pip install spire-doc

Spire.Doc для Python предоставляет бесплатную версию, которая поддерживает базовые операции с документами Word, что вполне достаточно для большинства задач на уровне абзацев, рассматриваемых в этой статье.

pip install spire-doc-free

Добавление абзаца

1. Добавление текста в конец документа Word

Добавление абзаца в конец документа — одна из самых распространённых операций при динамической генерации файлов Word.

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

doc = Document()

doc.LoadFromFile("Input.docx")

# Получение последнего раздела

lastSection = doc.LastSection

# Добавление абзаца в раздел

paragraph = lastSection.AddParagraph()

# Добавление текста в абзац

paragraph.AppendText("Это новый абзац.")

# Сохранение документа

doc.SaveToFile("AddParagraphAtEnd.docx", FileFormat.Docx2019)

doc.Dispose()

Этот подход идеально подходит для добавления заключений, резюме или добавленных материалов.

2. Вставка абзаца в определённое место

Иногда вам может потребоваться вставить абзац в точном месте, а не добавлять его в конец.

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

doc = Document()

doc.LoadFromFile("Input.docx")

# Получение специфического раздела

section = doc.Sections[0]

# Создание абзаца

paragraph = Paragraph(doc)

paragraph.AppendText("Это новый абзац.")

# Вставка абзаца как третьего (индекс начинается с 0)

section.Paragraphs.Insert(2, paragraph)

# Сохранение документа

doc.SaveToFile("InsertParagraph.docx", FileFormat.Docx2019)

doc.Dispose()

Это особенно полезно при работе с шаблонами, где контент должен появляться в фиксированном порядке.

3. Настройка форматирования абзаца

Вы также можете применять пользовательское форматирование к вновь добавленным абзацам с помощью стилей.

# Создание стиля абзаца

style = ParagraphStyle(doc)

style.Name = "NewStyle"

style.CharacterFormat.FontName = "Times New Roman"

style.CharacterFormat.FontSize = 12

doc.Styles.Add(style)

# Применение стиля к абзацу

paragraph.ApplyStyle(style.Name)

Использование стилей вместо ручного форматирования помогает поддерживать последовательность во всём документе.

Удаление абзаца

1. Удаление абзаца по индексу

Если вы знаете положение абзаца, который хотите удалить, удаление по индексу — это просто.

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

doc = Document()

doc.LoadFromFile("Input.docx")

# Получение специфического раздела

section = doc.Sections[0]

# Удаление четвёртого абзаца

section.Paragraphs.RemoveAt(3)

# Сохранение документа

doc.SaveToFile("RemoveParagraph.docx", FileFormat.Docx2019)

doc.Dispose()

💡 Вы также можете удалить все абзацы, используя section.Paragraphs.Clear(), если это необходимо.

2. Удаление абзаца, содержащего определённый текст

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

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

doc = Document()

doc.LoadFromFile("Input.docx")

# Получение специфического раздела

section = doc.Sections[0]

# Поиск всех вхождений указанного текста

textSelections = doc.FindAllString("Целевой текст", False, True)

# Цикл по всем вхождениям

for selection in textSelections:

textRange = selection.GetAsOneRange()

owner_paragraph = textRange.OwnerParagraph

section.Paragraphs.Remove(owner_paragraph)

# Сохранение документа

doc.SaveToFile("RemoveCertainParagraph.docx", FileFormat.Docx2019)

doc.Dispose()

Этот метод очень эффективен для очистки заполнительного контента в шаблонах.

Удаление пустых/незаполненных абзацев

1. Удаление абзацев без текста

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

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

doc = Document()

doc.LoadFromFile("Input.docx")

# Получение специфического раздела

section = doc.Sections[0]

# Перебор с конца вперед

for i in range(section.Paragraphs.Count - 1, -1, -1):

paragraph = section.Paragraphs[i]

has_non_text_content = False

for j in range(paragraph.ChildObjects.Count):

obj = paragraph.ChildObjects[j]

if obj.DocumentObjectType != DocumentObjectType.TextRange:

has_non_text_content = True

break

if not has_non_text_content and (paragraph.Text == "" or paragraph.Text.isspace()):

section.Paragraphs.RemoveAt(i)

# Сохранение документа

doc.SaveToFile("RemoveBlankParagraphs.docx", FileFormat.Docx2019)

doc.Dispose()

2. Очистка лишних разрывов строки

Лишние разрывы строки могут выглядеть неаккуратно в документе. Вы можете удалить их, просканировав дочерние объекты абзаца.

from spire.doc import *

from spire.doc.common import *

# Загрузка документа Word

document = Document()

document.LoadFromFile("Input.docx")

# Получение первого раздела

section = document.Sections[0]

# Перебор всех абзацев

for j in range(section.Paragraphs.Count):

paragraph = section.Paragraphs[j]

for i in range(paragraph.ChildObjects.Count - 1, -1, -1):

obj = paragraph.ChildObjects[i]

if obj.DocumentObjectType == DocumentObjectType.Break:

try:

if hasattr(obj, 'BreakType') and obj.BreakType == BreakType.LineBreak:

paragraph.ChildObjects.RemoveAt(i)

except:

paragraph.ChildObjects.RemoveAt(i)

# Сохранение документа

document.SaveToFile("RemoveLineBreaks.docx", FileFormat.Docx)

document.Dispose()

Заключительные мысли

Добавление и удаление абзацев программно — это основное умение при работе с документами Word в Python.

С помощью Spire.Doc для Python вы можете точно контролировать содержание, положение, форматирование и логику очистки абзацев.

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

Показать полностью
8

Учебник по Python: Легко конвертируйте DOCX в TXT и TXT в DOCX

Конвертация между DOCX (документы Word) и TXT (простые текстовые файлы) — это обычная задача в обработке документов, извлечении данных и автоматизации рабочих процессов. В этом посте блога мы рассмотрим, как конвертировать DOCX в TXT и TXT в DOCX, используя библиотеку Free Spire.Doc для Python .

Зачем конвертировать между DOCX и TXT?

DOCX файлы богаты форматированием и поддерживают различные функции, такие как изображения, стили и гиперссылки. Однако они могут быть громоздкими, когда вам нужен только простой текст для быстрых правок или извлечения данных. С другой стороны, TXT файлы лёгкие и универсально совместимы, но не имеют форматирования.

Конвертация между этими форматами предоставляет гибкость в обработке документов, позволяя вам:

  • Извлекать чистый текст из отформатированных документов

  • Превращать простой текст в профессионально оформленные документы

  • Упрощать рабочие процессы обработки документов

Предварительные требования

Перед тем, как погрузиться в код, убедитесь, что у вас есть следующее:

  1. Установленный Python на вашем компьютере.

  2. Библиотека Free Spire.Doc для Python . Вы можете установить её с помощью pip:
    bash

    pip install spire.doc.free

  3. Текстовый редактор или IDE для написания кода на Python.

  4. Примерные файлы DOCX и TXT для тестирования.

Конвертация DOCX в TXT на Python

Следующий код читает документ Word (Sample.docx) и сохраняет его содержимое в качестве простого текстового файла (DocxToTxt.txt).

from spire.doc import *

from spire.doc.common import *

# Создать объект Document

document = Document()

# Загрузить файл docx

document.LoadFromFile("C:/Users/Administrator/Desktop/Sample.docx")

# Сохранить файл docx в формате txt

document.SaveToFile("DocxToTxt.txt", FileFormat.Txt)

document.Close()

В этом коде:

  • Создаётся объект Document для работы.

  • Метод LoadFromFile используется для загрузки файла DOCX из указанного пути.

  • Документ сохраняется в формате TXT с использованием метода SaveToFile.

Конвертация TXT в DOCX на Python

В зависимости от того, хотите ли вы применить форматирование программно, вы можете конвертировать текстовый файл (TXT) в файл DOCX, используя один из следующих двух методов:

Метод 1: Простое решение (без форматирования)

Этот базовый подход создаёт документ Word с содержимым TXT, но без специального форматирования.

from spire.doc import *

from spire.doc.common import *

# Создать объект Document

document = Document()

# Загрузить файл txt

document.LoadFromFile("C:/Users/Administrator/Desktop/Sample.txt")

# Сохранить файл txt как файл docx

document.SaveToFile("TxtToDocx.docx", FileFormat.Docx2016)

document.Close()

В этом коде:

  • Создаётся объект Document.

  • Файл TXT загружается с помощью метода LoadFromFile.

  • Документ затем сохраняется в формате DOCX.

Метод 2: Расширенное решение (с форматированием)

Для более профессиональных результатов вы можете применить форматирование во время конвертации:

from spire.doc import *

# Функция для форматирования textRange

defformat_textRange(textRange, font_name, font_size, color):

# Установить свойства шрифта

textRange.CharacterFormat.FontName = font_name

textRange.CharacterFormat.FontSize = font_size

textRange.CharacterFormat.TextColor = color

# Чтение файла TXT и разделение на абзацы

withopen("C:/Users/Administrator/Desktop/Sample.txt", "r") as file:

content = file.read()

# Разделение содержимого на абзацы с помощью пустых строк

paragraphs = content.split('\n\n')

# Создать новый объект Document

document = Document()

section = document.AddSection()

section.PageSetup.Margins.All = 40

# Обработка каждого абзаца и добавление его в документ

for idx, para inenumerate(paragraphs):

# Удалить пробелы и пропустить пустые абзацы

para = para.strip()

ifnot para:

continue

# Создать новый абзац в документе

new_paragraph = section.AddParagraph()

text_range = new_paragraph.AppendText(para)

# Применить разные форматы в зависимости от индекса абзаца

if idx % 2 == 0: # Пример: четные абзацы

format_textRange(text_range, font_name="Times New Roman", font_size=18, color=Color.get_Red())

else: # Нечётные абзацы

format_textRange(text_range, font_name="Times New Roman", font_size=13, color=Color.get_Blue())

# Добавить пустой абзац после каждого форматированного абзаца

section.AddParagraph()

# Сохранить документ как DOCX

document.SaveToFile("TxtToFormattedDocx.docx", FileFormat.Docx2016)

document.Dispose()

В этом коде:

  • Определена функция format_textRange для применения определённых свойств шрифта (название шрифта, размер и цвет) к объекту TextRange.

  • Файл TXT открывается, его содержимое читается и разделяется на абзацы на основе пустых строк.

  • Создаётся объект Document, и добавляется секция с указанными полями.

  • Каждый абзац обрабатывается, форматируется и добавляется в документ. Чётные абзацы оформляются красным цветом и большим размером, а нечётные — синим и меньшим размером.

  • Пустой абзац создаётся после каждого форматированного абзаца для улучшения читаемости.

  • Наконец, документ сохраняется как файл DOCX.

Заключение

В этом посте блога мы продемонстрировали, как конвертировать DOCX в TXT для извлечения содержимого обычного текста, что делает работу с текстовыми данными более удобной без отвлекающего форматирования.

Кроме того, мы показали, как конвертировать TXT в DOCX, предлагая как базовые, так и расширенные варианты форматирования для улучшения общего представления вашего текста.

Показать полностью 3
4

Как добавить или удалить страницы в PDF с помощью Python

Как добавить или удалить страницы в PDF с помощью Python

Управление страницами PDF — будь то добавление новых страниц или удаление ненужных — является распространённой задачей в автоматизированной обработке документов. Python в сочетании с Spire.PDF для Python делает эти операции быстрыми, надежными и простыми в реализации.

В этом руководстве вы узнаете, как:

  • Вставить страницы в любое место в PDF

  • Удалить конкретную страницу

  • Автоматически обнаруживать и удалять пустые страницы

Установка необходимой библиотеки

Чтобы работать с PDF-файлами, установите Spire.PDF для Python :

pip install spire.pdf

Примечание: Для работы с PDF с менее чем 10 страницами доступна бесплатная версия, которую также можно установить через PyPI :

pip install spire.pdf.free

Затем импортируйте необходимые модули в ваш скрипт:

from spire.pdf.common

import * from spire.pdf import *

После установки вы готовы загружать, изменять и сохранять PDF-документы через Python .

Добавление новых страниц в PDF (в начале, в середине или в конце)

Добавление страниц — это обычная необходимость при подготовке отчетов , вставке титульной страницы или добавлении пустых страниц для заметок . Spire.PDF позволяет вам вставлять пустые страницы в любое место: в начале, середине или в конце документа.

Пример кода: Вставка страниц в конкретные позиции

from spire.pdf.common import *

from spire.pdf import *

# Создание объекта PdfDocument

doc = PdfDocument()

# Загрузка PDF-документа

doc.LoadFromFile("Input.pdf")

# Вставка пустой страницы в начале как первой страницы

doc.Pages.Insert(0)

# Вставка пустой страницы как второй страницы

doc.Pages.Insert(1)

# Добавление пустой страницы в конец документа

doc.Pages.Add(PdfPageSize.A4(), PdfMargins(0.0, 0.0))

# Сохранение результирующего документа

doc.SaveToFile("AddPages.pdf")

doc.Close()

Как это работает

Pages.Insert(index) вставляет пустую страницу в указанную позицию.

Pages.Add(size, margins) добавляет пустую страницу в конец PDF.

Индексы страниц начинаются с нуля:

  • 0 → первая страница

  • 1 → вторая страница и т.д.

Удаление конкретной страницы из PDF

Если ваш PDF содержит устаревший контент , образцы страниц или страницы, вставленные в процессе обработки, вы можете удалить их, используя их индекс.

Пример кода: Удаление страницы

from spire.pdf.common import *

from spire.pdf import *

# Создание объекта PdfDocument

doc = PdfDocument()

# Загрузка PDF-документа

doc.LoadFromFile("Input.pdf")

# Удаление второй страницы документа

doc.Pages.RemoveAt(1)

# Сохранение результирующего документа

doc.SaveToFile("DeletePage.pdf")

doc.Close()

Совет: Если вам нужно удалить несколько страниц, удаляйте их в порядке убывания, чтобы избежать смещения индексов.

Обнаружение и удаление пустых страниц в PDF

Пустые страницы часто появляются во время сканирования или пакетной конверсии . Spire.PDF предоставляет два полезных подхода:

  • Используйте page.IsBlank() — обнаруживает полностью пустые страницы.

  • Отрендерите страницу в изображение и проверьте данные пикселей — обнаруживает визуально пустые страницы, которые технически содержат невидимые объекты.

Ниже представлена комбинированная реализация.

Пример кода: Автоматическое удаление пустых страниц

import io

from spire.pdf import PdfDocument

from PIL import Image

# Пользовательская функция: Проверка, является ли изображение пустым (все пиксели белые)

defis_blank_image(image):

# Конвертирование в RGB-режим и получение пикселей

img = image.convert("RGB")

# Получение всех точек пикселей и проверка, все ли они белые

white_pixel = (255, 255, 255)

returnall(pixel == white_pixel for pixel in img.getdata())

# Загрузка PDF-документа

doc = PdfDocument()

doc.LoadFromFile("Input.pdf")

# Проход по каждой странице в обратном порядке, чтобы избежать проблем с индексами при удалении

for i inrange(doc.Pages.Count - 1, -1, -1):

page = doc.Pages[i]

# Проверка, является ли текущая страница полностью пустой

if page.IsBlank():

# Если она полностью пустая, удалить её из документа

doc.Pages.RemoveAt(i)

else:

# Конвертировать текущую страницу в изображение

with doc.SaveAsImage(i) as image_data:

image_bytes = image_data.ToArray()

pil_image = Image.open(io.BytesIO(image_bytes))

# Проверить, является ли изображение пустым

if is_blank_image(pil_image):

# Если это пустое изображение, удалить соответствующую страницу из документа

doc.Pages.RemoveAt(i)

# Сохранить результирующий PDF

doc.SaveToFile("RemoveBlankPages.pdf")

doc.Close()

Почему этот метод работает

  • IsBlank() обнаруживает истинные пустые страницы.

  • Рендеринг в изображение помогает обнаружить страницы, содержащие:

    • невидимый текст

    • пустые слои рисования

    • лишние объекты

  • Обработка в обратном порядке обеспечивает безопасное удаление без конфликтов индексов.

Резюме

Управление страницами PDF с помощью Python становится простым благодаря Spire.PDF для Python . В этом учебном руководстве вы узнали, как:

  • Вставить пустые страницы в любое место в PDF

  • Удалить конкретную страницу по индексу

  • Обнаружить пустые или визуально пустые страницы и удалить их

Эти техники являются необходимыми для создания автоматизированных рабочих процессов, очистки PDF-файлов и подготовки документов для печати или архивации .

Показать полностью

Продвиньте ваш пост

Перейти

Нужно больше внимания к постам? Есть способ!

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

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

Продвинуть пост

7

Машинное обучение на Московской бирже - что из этого не вышло

Время после нового года решил провести с пользой и окунуться в машинное обучение. Заняться Machine Learning — и посмотреть получится что‑то или нет с российским рынком акций на Московской бирже.

Моей целью было построить такую систему, которая будет учиться на истории и в перспективе торговать лучше чем случайное блуждание 50/50. Но из‑за комиссий и спреда подобные блуждания изначально отрицательны — чтобы выйти в плюс надо как минимум покрывать комиссии.

Если говорить о результатах очень кратко, то технически всё работает, но вот финансовый результат на грани безубыточности.

Если Вы только интересуетесь этой темой Вы можете посмотреть какие‑то шаги в моей статье, а если Вы уже опытный разработчик подобных систем, то можете подсказать что‑нибудь в комментариях.

Причём вся эта работа выглядит совершенно не так как показывается в фильмах про уолл‑стрит: фактически это написание скриптов и монотонный запуск и всё происходит полностью локально на компьютере.

Скриншот VS Code открытым деревом проекта

Скриншот VS Code открытым деревом проекта

Охота за данными

Вообще данные очень важны. Иначе получается что мусор на входе просто перетекает в мусор на выходе.

Для отбора бумаг я руководствовался следующей логикой: сначала ищу общий список всех акций, торгуемых на Московской бирже и делаю выборку — в неё входят только те, у которых есть фьючерсы. Дальше оставляю только тикеры акций, которые имеют фьючерсы.

Потом беру два API — одно от брокера, а второе API, предоставляющее информацию по всем юридическим лицам России — это API DaData. У каждой акции ведь есть ИНН компании. Используя оба этих API — оба бесплатных кстати — обогащаю каждую запись дополнительными сведениями.

Фрагмент файла tickers_full_market.json с общим список тикеров

Фрагмент файла tickers_full_market.json с общим список тикеров

После этого скачиваю котировки акций с Московской биржи. И загружаю три индекса: IMOEX, IMOEX2, RTSI, RGBI.

Для этого скачиваю минутки — они готовые и сразу в архивах через API брокера — можно очень быстро скачать полностью все бумаги.

С индексами сложнее. Брокерский API не отдавал историю по IMOEX и RGBI, видимо, из‑за ограничений лицензии биржи (привет, MOEX AlgoPack). Пришлось писать парсер для прямого API Московской биржи (ISS MOEX) — скорость гораздо медленнее, но я скачиваю тоже минутки. Скачать все доступные минутки с IMOEX, IMOEX2, RTSI, RGBI занимает около 20 минут.

Котировки индекса

Котировки индекса

Работа со временем

Я начал работу с того, что выделил три интересующих меня таймфрейма. 15 минут, 1 час и 1 день, основной 1 час.

Написал скрипт который преобразует архивы с минутками от API брокера в файлы с котировками нужных таймфреймов.

Итерация 1,3,4: временнЫе бары (обычные)

Сначала я просто агрегировал минутки в 15 минут, 1 час и 1 день через скрипт, но рынок неравномерен. Возможно для ML‑модели временные свечи могут быть очень шумные, так как содержат разное количество информации.

Скрипт <!--noindex--><a href="https://pikabu.ru/story/mashinnoe_obuchenie_na_moskovskoy_birzhe__chto_iz_yetogo_ne_vyishlo_13590580?u=http%3A%2F%2Fnormalization_quotes_stock.py&t=normalization_quotes_stock.py&h=7d5b34c667247b143caeb2933fb71e45a72ca18b" title="http://normalization_quotes_stock.py" target="_blank" rel="nofollow noopener">normalization_quotes_stock.py</a><!--/noindex--> который читает 1-минутные архивы (ZIP) из quotes/1min_zip и агрегирует данные в 15min, 1h, 1d

Скрипт normalization_quotes_stock.py который читает 1-минутные архивы (ZIP) из quotes/1min_zip и агрегирует данные в 15min, 1h, 1d

Итерация 2: свечи рублевого объема

Потом я временно перешёл к событийным барам. Новая свеча формируется не по времени, а когда проходит фиксированный объем в рублях, например, 50 млн руб., но для разных акций этот порог разный, потому что рассчитывается динамически. Разделил их по условным классам:

  • A: порог выше.

  • B: порог ниже.

  • C: отбрасываются.

Скрипт который создаёт из минутных котировок свечи рублевого объема и классифицирует бумаги по классам

Скрипт который создаёт из минутных котировок свечи рублевого объема и классифицирует бумаги по классам

Учитель для робота. Разметка

Как объяснить машине, что такое «хорошая сделка»? Рынок может продолжать рост, но перед этим выбить по стопу.

Книга Маркос Лопез де Прадо <a href="https://pikabu.ru/story/mashinnoe_obuchenie_na_moskovskoy_birzhe__chto_iz_yetogo_ne_vyishlo_13590580?u=https%3A%2F%2Fhabr.com%2Fru%2Fcompanies%2Fpiter%2Farticles%2F454778%2F&t=%C2%AB%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5%20%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%3A%20%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B%20%D0%B4%D0%BB%D1%8F%20%D0%B1%D0%B8%D0%B7%D0%BD%D0%B5%D1%81%D0%B0%C2%BB&h=5d11d1e39fdf50831615b0bd2374e1f4bdf216a0" title="https://habr.com/ru/companies/piter/articles/454778/" target="_blank" rel="nofollow noopener">«Машинное обучение: алгоритмы для бизнеса»</a>

Книга Маркос Лопез де Прадо «Машинное обучение: алгоритмы для бизнеса»

Для установки цели я использовал тройной барьер по де Прадо:

  • Верхний барьер (Take Profit): Цена + N×ATR

  • Нижний барьер (Stop Loss): Цена - M×ATR

  • Вертикальный барьер (Time Limit): Если прошло 100 баров, а цена никуда не пришла — выходим.

Скрипт расставляет метки:

Метка 1: сработал Take Profit.

Метка 0: вышло время, выход в ноль (минус комиссия).

Метка -1: сработал Stop Loss, потеря денег.

Фрагмент в Visual Studio Code

Фрагмент в Visual Studio Code

Глаза модели: инженерия признаков

Я использовал CatBoost (Categorical Boosting) это библиотека машинного обучения с открытым исходным кодом от «Яндекса», основанная на градиентном бустинге над деревьями решений. Я не подаю сырые цены (OHLCV: Open (цена открытия), High (максимальная цена), Low (минимальная цена), Close (цена закрытия) и Volume (объем торгов)), так как они не стационарны, потому что цена 100 ₽ в 2010 и 100 ₽ в 2024 — это разные сущности, а использую только относительные величины.

Я старался подавать именно Log Returns (логарифмические доходности), потому что Log returns аддитивны и симметричны: падение на 50% и рост на 100% имеют одинаковый масштаб в логарифмах.

Сами признаки, в разных итерациях по разному было:

  • Качество импульса: не просто «цена выросла», а как она выросла. Использую автокорреляцию и эффективность тренда.

  • Микроструктура: что происходило внутри этой свечи рублевого объема? Какая концентрация объема?

  • Межрыночные связи: как актив ведет себя относительно индекса Мосбиржи и индекса гособлигаций RGBI.

  • Классика: RSI (нормализованный через Z‑score), расстояния до скользящих средних.

Файл для генерации признаков и разметки

Файл для генерации признаков и разметки

Моделирование

Для того чтобы заниматься ML все инструменты у меня были: компьютер 32 Гб оперативки с видеокартой GPU 16 Гб, Python как основной язык, Docker чтобы не зависеть от капризов драйверов, Numba для ускорения расчётов, Linux для администрирования Docker контейнеров.

Для моей задачи как будто даже избыточная конфигурация — потому что все расчёты протекают очень быстро.

Dockerfile

Dockerfile

Делаю это из под Ubuntu, хотя всю разработку веду из‑под Windows.

<!--noindex--><a href="https://pikabu.ru/story/mashinnoe_obuchenie_na_moskovskoy_birzhe__chto_iz_yetogo_ne_vyishlo_13590580?u=http%3A%2F%2F01_build.sh&t=01_build.sh&h=ac7dfe60524a01fe84c6258e87150fb435794737" title="http://01_build.sh" target="_blank" rel="nofollow noopener">01_build.sh</a><!--/noindex-->

01_build.sh

Ещё использую измененную версию пошагового тестирования (Walk‑Forward Optimization), которая используется в трейдинге для поиска и проверки торговых стратегий, но добавляя «очистку» (purging) данных: она избегает перекрытия обучающих и тестовых периодов, чтобы предотвратить подгонку стратегии под шум истории, делая результаты более реалистичными и устойчивыми к будущим изменениям рынка.

Результаты и боль

При просмотре результатов магия машинного обучения быстро испаряется.

Я учитываю комиссии:

COMMISSION_PCT = 0.04 / 100  # комиссия брокера
SLIPPAGE_PCT  = 0.02 / 100  # проскальзывание 

Каждая сделка автоматически теряет 0,06% или 0,12% на круг для акций. Кажется мелочью, но при сотнях сделок именно эти десятые доли процента превращают модель в убыточную. Модели нужно предсказывать движения >0,3-0,5%, чтобы быть в плюсе.

По качеству прогнозов мой ML стабильно показывает AUC 0,54–0,55. Формально это лучше случайного угадывания (0.50), но до Грааля тут очень далеко. Почему? Даже небольшая ошибка в вероятностях, умноженная на комиссии и шум, быстро съедает весь перевес.

Чтобы понимать, что именно я меряю, важно разобраться в трёх ключевых метриках.

AUC (Area Under the Curve) — это мера того, насколько хорошо модель умеет отличать «хорошие» сделки от «плохих». Если AUC = 0.5, модель — это монетка. Если 0.55 — она угадывает чуть чаще, чем случайность. В вакууме это звучит неплохо, но в трейдинге такого преимущества часто недостаточно, чтобы перекрыть издержки.

Fold — это один из прогонов в Walk‑Forward Optimization. История рынка режется на последовательные отрезки: на одном модель учится, на следующем тестируется. Каждый такой отрезок — отдельный fold. Это имитация реальности: мы всегда торгуем на будущем, которого модель «не видела». Поэтому один fold может быть прибыльным, а следующий — убыточным, просто потому что режим рынка поменялся.

Тесты

Тесты

Precision (точность) — это ответ на вопрос: «если модель сказала „покупай“, как часто она оказывается права?». Это критично для торговли, потому что даже модель с неплохим AUC может генерировать кучу ложных сигналов, которые будут съедать депозит комиссиями и стоп‑лоссами.

И вот здесь появляется самая болезненная часть. На одном из фолдов я получаю красивую Equity Curve, где капитал растёт.

График fold_2_best_equity

График fold_2_best_equity

На другом — та же самая модель превращает счёт в “пилу”: заработали на тренде, потом долго и мучительно всё отдали на боковике.

График fold_3_best_equity

График fold_3_best_equity

Когда я писал этот текст мне в голову пришло, а что если модель обучать на максимизацию финансового показателя, такого как Коэффициент Шарпа?

Заключение: вопросы к залу

Я проделал некоторую работу, но результаты пока выглядят не особо приятными.

Мои гипотезы:

  1. Ошибка в методологии?

  2. Мало данных?

  3. Предсказывать не направление, а волатильность?

  4. Перейти на более высокие таймфреймы (4H, 1D), где комиссия съедает меньшую долю движения?

  5. Нужно использовать данные из стакана (Order Book)? С получением истории стакана для частного лица большие проблемы. Бесплатно доступен лишь очень ограниченный набор инструментов.

  6. CatBoost слишком прост, нужны трансформеры?

Я занимаюсь Machine Learning (ML), когда система учится на таблицах. Но есть ведь ещё Deep learning (глубокое обучение) когда идёт анализ больших объёмов данных и выявления сложных закономерностей автономно. Но боюсь для моей задачи слишком мало данных. Наверное только на истории стаканов OrderBook будет работать.

Приглашаю в комментарии: кто реально запускал Machine Learning на Мосбирже в плюс? Или просто опытных людей. Где я свернул не туда?

Не сдерживайте себя — напишите комментарий — буду рад любой критике в комментариях.

Автор: Михаил Шардин
🔗 Моя онлайн‑визитка
📢 Telegram «Умный Дом Инвестора»

13 января 2026 г.

Показать полностью 13
6

Python File Executor – Запускайте Python скрипты одним кликом с автоматической установкой зависимостей!

Python File Executor – Запускайте Python скрипты одним кликом с автоматической установкой зависимостей!

Мое первое приложение в серии "Мамкин Вейб - Кодер"

📋 Что это такое?

Python File Executor – это продвинутый графический инструмент на Tkinter для удобного запуска Python-скриптов прямо из интерфейса Windows. Больше не нужно вручную открывать командную строку или беспокоиться о недостающих библиотеках – приложение сделает всё за вас!

Скачать с Яндекс диска: https://disk.yandex.ru/d/faoRWLQrzU5hnw

✨ Ключевые возможности:

🎯 1. Умный анализ зависимостей

  • Автоматическое обнаружение импортов – программа анализирует ваш скрипт и находит все необходимые библиотеки

  • Игнорирование стандартных модулей – не предлагает установить os, sys и другие встроенные библиотеки

  • Поддержка альтернативных имен – понимает, что sklearn = scikit-learn, cv2 = opencv-python и т.д.

🔧 2. Автоматическая установка

  • Одним кликом устанавливает все зависимости через pip

  • Визуальный прогресс установки – видите, что именно происходит

  • Безопасность – запрашивает подтверждение перед установкой

⚡ 3. Запуск в PowerShell

  • Интеграция с PowerShell – скрипты выполняются в родной среде

  • Реальное время вывода – видите результаты выполнения по мере поступления

  • Цветное оформление вывода – легко различать ошибки, предупреждения и успешные сообщения

🛠 4. Дополнительные инструменты

  • 📝 Открыть в редакторе – быстрый доступ к редактированию скрипта

  • 📂 Открыть папку – удобная навигация по файловой системе

  • 📊 Детальная информация – размер файла, путь, статус зависимостей

Цветовая схема:

  • 🟦 Синий – основные действия

  • 🟩 Зеленый – успешные операции

  • 🟧 Оранжевый – предупреждения/зависимости

  • 🟥 Красный – ошибки

  • 🟪 Фиолетовый – информация о зависимостях

📁 Как это работает?

Шаг 1: Выбор скрипта

Просто нажмите кнопку "Выбрать .py файл" и выберите свой Python-скрипт.

Шаг 2: Автоматический анализ

Программа автоматически:

  • Сканирует все импорты в файле

  • Определяет, какие библиотеки уже установлены

  • Показывает список отсутствующих зависимостей

Шаг 3: Установка зависимостей (при необходимости)

Нажмите "Установить зависимости" – программа:

  • Установит все недостающие библиотеки через pip

  • Покажет прогресс установки в реальном времени

  • Обновит статус после завершения

Шаг 4: Запуск скрипта

Нажмите "Выполнить в PowerShell" – скрипт:

  • Запустится в интегрированном PowerShell

  • Будет выводить результаты выполнения в окно программы

  • Покажет код завершения (0 = успех)

🎯 Для кого этот инструмент?

👨‍💻 Разработчики:

  • Быстро тестируйте свои скрипты

  • Не тратьте время на ручную установку зависимостей

  • Удобный просмотр логов выполнения

👩‍🏫 Преподаватели и студенты:

  • Идеально для учебных проектов

  • Автоматическая настройка среды выполнения

  • Наглядный процесс установки библиотек

🧪 Тестировщики:

  • Быстрый запуск тестовых скриптов

  • Удобное отслеживание ошибок зависимостей

  • Повторяемость выполнения

🚀 Начинающие программисты:

  • Не нужно разбираться с командной строкой

  • Автоматическое решение проблем с импортами

  • Визуальная обратная связь

🔧 Технические особенности

Поддерживаемые сценарии:

  • ✅ Простые скрипты с несколькими библиотеками

  • ✅ Сложные проекты с множеством зависимостей

  • ✅ Скрипты с пользовательским вводом (stdin)

  • ✅ Длительные операции с прогрессом

Безопасность:

  • 🔒 Запрос подтверждения перед установкой

  • 🔒 Использует официальный pip

  • 🔒 Показывает, что именно будет установлено

  • 🔒 Возможность отменить установку

📊 Пример использования

Сценарий: У вас есть скрипт для анализа данных:

С помощью Python File Executor:

  1. Выбираете файл → программа видит 4 зависимости

  2. Проверяете зависимости → оказывается, sklearn не установлен

  3. Устанавливаете зависимости → программа ставит scikit-learn

  4. Запускаете скрипт → видите результаты в красивом интерфейсе

🎁 Особенности реализации

Умный парсер импортов:

  • Поддержка многострочных импортов

  • Игнорирование комментариев

  • Обработка псевдонимов (import numpy as np)

  • Распознавание from module import function

Пользовательский интерфейс:

  • Современный плоский дизайн

  • Интуитивная навигация

  • Адаптивная компоновка

  • Информативный статус-бар

Стабильность работы:

  • Обработка ошибок на каждом этапе

  • Безопасное завершение процессов

  • Восстановление после сбоев

  • Логирование всех операций

👥 Для сообщества

Вклад приветствуется! Хотите улучшить инструмент?

  • Сообщайте о багах

  • Предлагайте новые функции

  • Участвуйте в разработке

🎯 Попробуйте Python File Executor уже сегодня и забудьте о сложностях запуска Python-скриптов!

#Python #Automation #DeveloperTools #PowerShell #Dependencies #Programming #Tkinter #Windows #Productivity

Показать полностью 1

Old File Delete

Серия Мои приложения

Данный пост рассказывает о моём первом опыте вайб-кодинга.

Old File Delete (OFD) — это легкая и эффективная утилита, разработанная для тех, кто ценит минимализм и порядок. Приложение помогает мгновенно очистить выбранные папки от накопившегося цифрового мусора.

Написано на Python, библиотека Tkinter.

Само приложение состоит из 1 экрана:

Old File Delete

Написано с помощью GPT-5-mini. Использовались всего 5 запросов, моих правок абсолютно нет:

Сделай приложение Old File Delete. Используй следующее описание:

Приложение сканирует папку и удаляет файлы, которые не изменялись более $N$ дней.

• os: Основная библиотека для работы с операционной системой. Используется для листинга файлов в директории (os.listdir) и их удаления (os.remove).

• pathlib: Современный интерфейс для работы с путями. Позволяет легко получить время последнего изменения файла (path.stat().st_mtime) и удобно манипулировать путями независимо от формата Windows.

• tkinter.filedialog: Часть стандартной библиотеки GUI. Нужна для вызова стандартного окна Windows, чтобы пользователь мог выбрать папку для очистки, а не вводить путь вручную.

Работаешь на питоне. Библиотека ткинтер. Вверху главного окна название, справа от него кнопка настроек.

Далее кнопка выбора папки, которую надо проверить. Далее текстовое поле для ввода времени в днях. Далее кнопка очистить. После очистки создаётся маленькое окошко, в котором написано, что все ок. В настройках возможность настройти язык. В самом начале работы читается файд "language.txt". В нём только 1 число. Если 1 то язык английский, если 2 то русский.

Убери из этого приложения настройки. Переделай все в бело-серые тона. Фон белый-очень светлый серый. Текст на фоне средне серый. Кнопка средне серый. Текст на кнопке очень светлый серый. фон окошка для числа дней также как и фон, только чуть светлее. Текст такой же. Название по центру. Снизу убери лишнее пространство

Язык только английский

Сделай текст больше до 24. Ужми побокам

Ширина 350

Можете скачать и протестировать его. Буду благодарен за конструктивную критику и идеи.

Сайт приложения:
http://temnik-projecs.tilda.ws/old-file-delete-ru

Скачать:
https://sourceforge.net/projects/old-file-delete/

Больше приложений:
http://temnik-projecs.tilda.ws/apps-ru

Показать полностью 1

Qwicker v5.3!

Серия Qwicker
<a href="https://pikabu.ru/story/qwicker_v53_13571405?u=https%3A%2F%2Fpikabu.ru%2Fstory%2Fqwicker_13531279&t=Qwicker&h=9e4bd8ad59095a9586ac90c805cfb5bb8b27ee1e" title="https://pikabu.ru/story/qwicker_13531279" target="_blank">Qwicker</a> - тут описание программы что это и зачем

Qwicker - тут описание программы что это и зачем

# Qwicker v5.3 — Новые возможности

## Визуальные улучшения

### Эффект свечения при наведении
- **Неоновое свечение** вокруг элементов при наведении курсора
- Полностью настраиваемый эффект:
- Размер свечения (от 0 до 50px)
- Цвет свечения (любой цвет палитры)
- Плавная анимация мигания с настраиваемой скоростью
- Поддержка всех форм элементов (круг, квадрат, скруглённый, шестиугольник и.т.д.)

### Система бейджей уведомлений
- **Визуальные счётчики** непрочитанных сообщений на элементах
- Автоматическое определение уведомлений из приложений (Telegram и др.)
- Полная настройка внешнего вида:
- Цвет бейджа
- Размер бейджа
- Размер текста
- Включение/выключение
- Умное форматирование чисел (99+ для больших значений)

## Технические улучшения

### Улучшенная стабильность
- **Автоматический перезапуск** системных listeners при обнаружении конфликтов
- Умное определение проблемных приложений
- Мониторинг состояния в реальном времени
- Защита от зависаний при работе с глобальными горячими клавишами

### Улучшения интерфейса
- Исправлены тексты заголовков в настройках
- Оптимизировано позиционирование элементов
- Улучшена производительность рендеринга

## Ключевые преимущества

**Более информативный интерфейс** — видите количество непрочитанных сообщений сразу
**Высокая стабильность** — автоматическое восстановление при сбоях
**Полная настройка** — каждый эффект можно настроить под себя

*Версия 5.3 — делаем работу с компьютером удобнее и красивее!*

Google disk
https://drive.google.com/file/d/1Pm1qy10gsYFhsPEGDmArPa9ATHA...

Показать полностью 1
691

Архитектурная ошибка или защита от взлома? Разбираем зависимость Home Assistant от онлайн-сервисов

Home Assistant позиционирует себя как локальную систему. Но я столкнулся с ситуацией, когда локальная функция (Samba) не работает из-за облачного сбоя. При этом я вообще не использую облако. В статье описываю как обошёл эту проблему за 5 минут, когда за день разобрался в причине.

Мне очень нравится Home Assistant как система управления умным домом, потому что она позволяет не зависеть от облаков и от падений интернета. Это не просто слова - с 2017 года я использую умный дом в обычной двухкомнатной хрущевке, и в основном всё работает. Но это скорее тестовый полигон для меня - я сам там не живу и поэтому очень ценю то что Home Assistant можно настроить один раз и если не обновлять, то несколько лет всё может спокойно проработать. А на этих новогодних каникулах у меня было время и я решил полностью обновить все дополнения и прошивки. Как оказалось зря - паранойя безопасности ломает определение Home Assistant как автономного сервиса, который можно использовать локально.

Небольшая предыстория: весь мой проект начался в 2017 году с идеи удаленного сбора показаний счётчиков квартиры, где я использовал самые доступные по цене решения: ESP8266, MegaD. Потом решил подключить управление светом через дешевые Sonoff с прошивкой Tasmota и OpenHAB. 1000 дней пользовался OpenHAB, а затем перешел на Home Assistant, а в 2024 году провёл ремонт и замену Wi-Fi реле на Zigbee. И до недавнего времени это работало.

В первых числах января 2026 решил удаленно обновить все зависимости - за несколько раз всё обновилось, но мне ещё понадобилось включить дополнение Samba share, чтобы из под Windows проверить пару конфигов, которые не хотели работать. А я отключил Samba share ещё год назад. Удаленно не смог включить - всё какая-то ошибка вылазила, хотя все остальные компоненты работают. Пришлось ехать на квартиру и думал что может быть Raspberry Pi 3 2015 года уже старая стала или флешка сдохла. У меня было ещё несколько запасных - прихватил и чистую флешку и новый микрокомпьютер 2017 года и новый блок питания.

"Стенд проверки"

"Стенд проверки"

Поставил чистую систему - в 2026 году это происходит через Raspberry Pi Imager, хочу с Windows компьютера подключиться, а там та же ошибка Не удалось сохранить конфигурацию дополнения, Unknown error, see supervisor logs. И непонятно из-за чего.

Ошибка Home Assistant Не удалось сохранить конфигурацию дополнения, Unknown error, see supervisor logs

Ошибка Home Assistant Не удалось сохранить конфигурацию дополнения, Unknown error, see supervisor logs

Только в логах на чистой системе подробно рассмотрел что WARNING (MainThread) [supervisor.utils.pwned] Can’t fetch HIBP data: Timeout

Ошибка Home Assistant WARNING (MainThread) [supervisor.utils.pwned] Can’t fetch HIBP data: Timeout

Ошибка Home Assistant WARNING (MainThread) [supervisor.utils.pwned] Can’t fetch HIBP data: Timeout

Стал разбираться и оказалось что Home Assistant абсолютно все пароли проверяет на  скомпромитированность через онлайн сервис, а поскольку мы в России, то этот сервис не даёт ответа видимо из-за санкций или политики, а в интерфейсе ничего внятного не пишет - просто неизвестная ошибка.

И я в своём полностью локальном Home Assistant не могу к нему по локальной сети подключиться из-за того что этот онлайн сервис HIBP не отвечает. Сервис HIBP (Have I Been Pwned) проверяет были ли заново создаваемые пароли в утечках данных.

Но какая-то нестыковка кажется с заявленной полной локальностью Home Assistant?

Home Assistant пользуется этим сервисом и это нельзя отключить для проверки безопасности паролей. Но я даже не знал что такая проверка есть, а у сервиса проблемы с доступностью в России из-за санкций или Роскомнадзора, что вызывает ошибки и блокирует работу всей домашней системы.

Как исправить ошибку WARNING (MainThread) [supervisor.utils.pwned] Can’t fetch HIBP data: Timeout

Поскольку у меня уже был физический доступ к SD карте - раз я приехал на удаленную квартиру, на которой установлен Home Assistant, то решил через физическое подключение к Linux провести все манипуляции, потому что функция PwnedConnectivityError блокирует абсолютно всё.

SD карта, подключенная к Linux

SD карта, подключенная к Linux

Нашёл проблему в файле pwned.py, он файл лежит внутри контейнера Supervisor, в моём случае по адресу admin:///media/mike/hassos-data/docker/overlay2/0e05ec32ffef35caed1b7184eefcfdda5eb1a35ad60e68e5d14f3a73996b18ea/diff/usr/src/supervisor/supervisor/utils.

Картридер в Ubuntu

Картридер в Ubuntu

Но у вас будет другой путь, надо искать внутри внутри контейнера Supervisor: /usr/src/supervisor/supervisor/utils/pwned.py

Файл /usr/src/supervisor/supervisor/utils/<!--noindex--><a href="https://pikabu.ru/story/arkhitekturnaya_oshibka_ili_zashchita_ot_vzloma_razbiraem_zavisimost_home_assistant_ot_onlaynservisov_13570135?u=http%3A%2F%2Fpwned.py&t=pwned.py&h=1a22d5b8f515012e396a2adbe93c582cbdbbb670" title="http://pwned.py" target="_blank" rel="nofollow noopener">pwned.py</a><!--/noindex-->

Файл /usr/src/supervisor/supervisor/utils/pwned.py

Вот оригинальный файл pwned.py с проблемой:

"""Small wrapper for haveibeenpwned.com API."""

import io
import logging

import aiohttp

from ..exceptions import PwnedConnectivityError, PwnedError, PwnedSecret

_LOGGER: logging.Logger = logging.getLogger(__name__)
_API_CALL: str = "https://api.pwnedpasswords.com/range/{hash}"

_CACHE: set[str] = set()


async def check_pwned_password(websession: aiohttp.ClientSession, sha1_pw: str) -> None:
"""Check if password is pwned."""
sha1_pw = sha1_pw.upper()

# Chech hit cache
sha1_short = sha1_pw[:5]
if sha1_short in _CACHE:
raise PwnedSecret()

_LOGGER.debug("Check pwned state of %s", sha1_short)
try:
async with websession.get(
_API_CALL.format(hash=sha1_short), timeout=aiohttp.ClientTimeout(total=10)
) as request:
if request.status != 200:
raise PwnedError(
f"Pwned service response with {request.status}", _LOGGER.warning
)
data = await request.text()

buffer = io.StringIO(data)
for line in buffer:
if not sha1_pw.endswith(line.split(":")[0]):
continue
_CACHE.add(sha1_short)
raise PwnedSecret()

except (aiohttp.ClientError, TimeoutError) as err:
raise PwnedConnectivityError(
f"Can't fetch HIBP data: {str(err) or 'Timeout'}", _LOGGER.warning
) from err

Файл /usr/src/supervisor/supervisor/utils/<!--noindex--><a href="https://pikabu.ru/story/arkhitekturnaya_oshibka_ili_zashchita_ot_vzloma_razbiraem_zavisimost_home_assistant_ot_onlaynservisov_13570135?u=http%3A%2F%2Fpwned.py&t=pwned.py&h=1a22d5b8f515012e396a2adbe93c582cbdbbb670" title="http://pwned.py" target="_blank" rel="nofollow noopener">pwned.py</a><!--/noindex-->

Файл /usr/src/supervisor/supervisor/utils/pwned.py

Вот моя изменненная версия pwned.py с полным отключением проблемного в России сервиса Have I Been Pwned (HIBP):

"""Small wrapper for haveibeenpwned.com API."""

import io
import logging

import aiohttp

from ..exceptions import PwnedConnectivityError, PwnedError, PwnedSecret

_LOGGER: logging.Logger = logging.getLogger(__name__)
_API_CALL: str = "https://api.pwnedpasswords.com/range/{hash}"

_CACHE: set[str] = set()


async def check_pwned_password(websession: aiohttp.ClientSession, sha1_pw: str) -> None:
"""Check if password is pwned."""
return None

"""
sha1_pw = sha1_pw.upper()

# Chech hit cache
sha1_short = sha1_pw[:5]
if sha1_short in _CACHE:
raise PwnedSecret()

_LOGGER.debug("Check pwned state of %s", sha1_short)
try:
async with websession.get(
_API_CALL.format(hash=sha1_short), timeout=aiohttp.ClientTimeout(total=10)
) as request:
if request.status != 200:
raise PwnedError(
f"Pwned service response with {request.status}", _LOGGER.warning
)
data = await request.text()

buffer = io.StringIO(data)
for line in buffer:
if not sha1_pw.endswith(line.split(":")[0]):
continue
_CACHE.add(sha1_short)
raise PwnedSecret()

except (aiohttp.ClientError, TimeoutError) as err:
raise PwnedConnectivityError(
f"Can't fetch HIBP data: {str(err) or 'Timeout'}", _LOGGER.warning
) from err
"""

После того как внёс изменения и вставил SD карту обратно в Raspberry Pi все пароли стало успешно сохранять и работоспособность полностью восстановилась.

Работоспособность сохранения паролей восстановилась

Работоспособность сохранения паролей восстановилась

Масштаб проблемы

Судя потому что я нашёл через поиск эта проблема существует уже несколько месяцев. Вот например похожий пример, когда человек пытался с ней справиться осенью 2025 года.

Мне кажется подобные решения очень сильно бьют по новичкам, которым реально сложно разобраться в подобных системах и ещё больше вопросов вызывает то что Home Assistant всегда был полностью локальной автономной системой, которую можно было настроить даже на даче и тут вылазит такая фишка.

Вообще мне кажется что стремление к безопасности — это хорошо, но вот делать зависимость от внешнего API для базовых локальных функций — это архитектурная ошибка.

Автор: Михаил Шардин
🔗 Моя онлайн‑визитка
📢 Telegram «Умный Дом Инвестора»

6 января 2026

Показать полностью 9
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества