Почему subprocess с PIPE может зависнуть
Дочерний процесс пишет в stdout, родитель вызывает
В разборе взаимной блокировки показано, почему каналы нужно читать во время работы процесса. Для ограниченного вывода удобен
Он использует
У
#python #процессы
Дочерний процесс пишет в stdout, родитель вызывает
wait(). На небольшом выводе всё работает. На большом буфер канала заполняется: ребёнок ждёт чтения, родитель — завершения ребёнка.В разборе взаимной блокировки показано, почему каналы нужно читать во время работы процесса. Для ограниченного вывода удобен
run():import subprocess
result = subprocess.run(
["python", "--version"],
capture_output=True,
text=True,
timeout=10,
check=True,
)
Он использует
communicate(), который обслуживает оба потока. Вывод при этом собирается в памяти, поэтому для больших логов выбирайте файл или потоковое чтение.У
Popen.communicate(timeout=...) другая тонкость: истечение тайм-аута само не убивает процесс. Нужны завершение процесса и повторный communicate() для чтения остатка вывода.#python #процессы
⚡1
Что проверить перед переходом на SQLAlchemy 2.1
Обновление зависимости может поменять драйвер подключения, даже если строка подключения осталась прежней.
В SQLAlchemy 2.1 адрес
Есть ещё два изменения: минимальная версия Python — 3.11, а
Перед обновлением прогоните сценарии подключения, транзакций и загрузки связей. Проверьте окружение CI: старая установленная зависимость может скрыть то, что сломается при чистой установке.
#python #sqlalchemy
Обновление зависимости может поменять драйвер подключения, даже если строка подключения осталась прежней.
В SQLAlchemy 2.1 адрес
postgresql:// по умолчанию выбирает psycopg, а oracle:// — oracledb. Если проект рассчитывает на конкретный DBAPI, укажите его явно и проверьте совместимость.Есть ещё два изменения: минимальная версия Python — 3.11, а
greenlet больше не устанавливается автоматически. Для асинхронных возможностей используйте:pip install "sqlalchemy[asyncio]"
Перед обновлением прогоните сценарии подключения, транзакций и загрузки связей. Проверьте окружение CI: старая установленная зависимость может скрыть то, что сломается при чистой установке.
#python #sqlalchemy
Как сделать бэкап работающей SQLite через Python
Просто скопировать файл активной базы рискованно. Во время копирования страницы могут изменяться, а при WAL часть данных находится в отдельном журнале.
Python предоставляет доступ к SQLite Online Backup API через
SQLite согласует копирование с работой базы. Получившаяся копия самостоятельна: следующие записи в исходник в неё не попадут.
Здесь
#python #sqlite
Просто скопировать файл активной базы рискованно. Во время копирования страницы могут изменяться, а при WAL часть данных находится в отдельном журнале.
Python предоставляет доступ к SQLite Online Backup API через
Connection.backup(). Метод вызывают у источника и передают ему соединение с приёмником:import sqlite3
from contextlib import closing
with closing(sqlite3.connect("app.db")) as src:
with closing(sqlite3.connect("backup.db")) as dst:
src.backup(dst)
SQLite согласует копирование с работой базы. Получившаяся копия самостоятельна: следующие записи в исходник в неё не попадут.
Здесь
closing нужен для закрытия соединений: обычный with connection управляет транзакцией, но не закрывает соединение. После бэкапа проверьте восстановление и чтение данных.#python #sqlite
❤2
UTF-8 по умолчанию не перекодирует старые файлы
В Python 3.15 текстовый ввод-вывод по умолчанию использует UTF-8. Это убирает часть различий между платформами, но файл в CP1251 остаётся файлом в CP1251.
В руководстве по переходу предлагают сначала найти операции с неявной кодировкой:
Предупреждения покажут выполненные вызовы, где кодировка не указана. Для остальных путей пригодится статическая проверка.
Указывайте
Не добавляйте
#python #файлы
В Python 3.15 текстовый ввод-вывод по умолчанию использует UTF-8. Это убирает часть различий между платформами, но файл в CP1251 остаётся файлом в CP1251.
В руководстве по переходу предлагают сначала найти операции с неявной кодировкой:
python -X warn_default_encoding app.py
Предупреждения покажут выполненные вызовы, где кодировка не указана. Для остальных путей пригодится статическая проверка.
Указывайте
encoding="utf-8" для UTF-8 и encoding="cp1251" для известных старых файлов. Если нужна именно кодировка локали пользователя, используйте encoding="locale".Не добавляйте
errors="ignore" ради исчезновения ошибки: так можно незаметно потерять символы. Перед обновлением проверьте реальные входные файлы, включая выгрузки из старых систем.#python #файлы
Почему тесты находят пакет, который забыли положить в сборку
При структуре, где пакет лежит в корне репозитория, Python может импортировать его прямо из рабочей директории. Тесты проходят, хотя установленный пакет может оказаться неполным.
В разборе структуры проекта предлагают для библиотек рассмотреть каталог
Теперь пакет обычно нужно установить, прежде чем импортировать. Это помогает заметить зависимость от файлов, случайно доступных в корне проекта.
Но установка для разработки и установка собранного wheel — разные проверки. Чтобы найти пропущенный шаблон или файл данных, соберите wheel и запустите тесты с ним в чистом окружении вне репозитория.
#python #тестирование
При структуре, где пакет лежит в корне репозитория, Python может импортировать его прямо из рабочей директории. Тесты проходят, хотя установленный пакет может оказаться неполным.
В разборе структуры проекта предлагают для библиотек рассмотреть каталог
src/:project/
├── pyproject.toml
├── src/
│ └── mypkg/
│ └── __init__.py
└── tests/
Теперь пакет обычно нужно установить, прежде чем импортировать. Это помогает заметить зависимость от файлов, случайно доступных в корне проекта.
Но установка для разработки и установка собранного wheel — разные проверки. Чтобы найти пропущенный шаблон или файл данных, соберите wheel и запустите тесты с ним в чистом окружении вне репозитория.
#python #тестирование
Что проверить при обновлении до Pydantic 2.14
Библиотека добавила поддержку Python 3.15 и прекратила поддержку 3.9. Поэтому обновление стоит начать с версий интерпретатора в CI и рабочих окружениях.
В анонсе Pydantic 2.14 есть улучшение для функций, принимающих выражения типов. TypeAdapter теперь использует TypeForm, благодаря чему совместимый анализатор может вывести результат
Это улучшает статическую проверку, но не заменяет выполнение валидации. Само указание аннотации ещё не проверяет внешние данные.
Для TypeForm нужны достаточно свежие анализаторы: авторы указывают Pyright 1.1.412 или Mypy 2.2 и новее. Перед обновлением проверьте также свои валидаторы, сериализацию и генерацию схем: в выпуск вошли небольшие изменения поведения.
#python #pydantic
Библиотека добавила поддержку Python 3.15 и прекратила поддержку 3.9. Поэтому обновление стоит начать с версий интерпретатора в CI и рабочих окружениях.
В анонсе Pydantic 2.14 есть улучшение для функций, принимающих выражения типов. TypeAdapter теперь использует TypeForm, благодаря чему совместимый анализатор может вывести результат
TypeAdapter(int | str) как int | str, а не неизвестный тип.Это улучшает статическую проверку, но не заменяет выполнение валидации. Само указание аннотации ещё не проверяет внешние данные.
Для TypeForm нужны достаточно свежие анализаторы: авторы указывают Pyright 1.1.412 или Mypy 2.2 и новее. Перед обновлением проверьте также свои валидаторы, сериализацию и генерацию схем: в выпуск вошли небольшие изменения поведения.
#python #pydantic
Одинаковые файлы, разные ZIP: почему меняется хеш
Два архива распаковываются в одинаковые файлы, но их SHA-256 различаются. Причиной могут быть даты записей, их порядок, права или настройки сжатия.
В разборе воспроизводимых архивов используют поддержку SOURCE_DATE_EPOCH в Python 3.14. При записи через
Дату лучше брать из неизменяемого события сборки, например коммита. Отдельно нужно сортировать имена, фиксировать содержимое и параметры сжатия. Явно переданный ZipInfo требует своей политики метаданных.
Проверка должна сравнивать байты двух сборок, а не только распакованные файлы. Для строгой воспроизводимости закрепите и версии инструментов: одинаковые исходники не гарантируют одинаковое сжатие в любой среде.
#python #сборка
Два архива распаковываются в одинаковые файлы, но их SHA-256 различаются. Причиной могут быть даты записей, их порядок, права или настройки сжатия.
В разборе воспроизводимых архивов используют поддержку SOURCE_DATE_EPOCH в Python 3.14. При записи через
writestr() с именем файла переменная позволяет задать стабильную дату вместо текущей.Дату лучше брать из неизменяемого события сборки, например коммита. Отдельно нужно сортировать имена, фиксировать содержимое и параметры сжатия. Явно переданный ZipInfo требует своей политики метаданных.
Проверка должна сравнивать байты двух сборок, а не только распакованные файлы. Для строгой воспроизводимости закрепите и версии инструментов: одинаковые исходники не гарантируют одинаковое сжатие в любой среде.
#python #сборка
🔥1
Ленивый импорт откладывает не только загрузку модуля
В Python 3.15 импорт можно отложить до первого обращения к имени. Это полезно для консольной утилиты, которая ради
Но выполнение модуля тоже переносится. Если импорт регистрировал плагин, а к имени никто не обратился, регистрация не произойдёт. Ошибка загрузки также может возникнуть позже привычного места импорта.
В руководстве по ленивым импортам предлагают сначала измерить их стоимость через
Новый синтаксис не разбирается старыми версиями Python. Для совместимого кода есть
#python #производительность
В Python 3.15 импорт можно отложить до первого обращения к имени. Это полезно для консольной утилиты, которая ради
--help загружает тяжёлые зависимости.# Python 3.15+
lazy import json
def parse(text):
return json.loads(text)
Но выполнение модуля тоже переносится. Если импорт регистрировал плагин, а к имени никто не обратился, регистрация не произойдёт. Ошибка загрузки также может возникнуть позже привычного места импорта.
В руководстве по ленивым импортам предлагают сначала измерить их стоимость через
-X importtime, затем отложить только нужные зависимости.Новый синтаксис не разбирается старыми версиями Python. Для совместимого кода есть
__lazy_modules__: старые интерпретаторы игнорируют этот список и выполняют обычный импорт.#python #производительность
✍1
Готовый сокет ещё не содержит всё сообщение
Selector сообщил, что сокет доступен для чтения. Это означает, что можно попробовать прочитать данные, а не что весь запрос уже пришёл.
В разборе модуля selectors показывают небольшой цикл обработки соединений. Сокеты переводят в неблокирующий режим, а данные накапливают в буфере конкретного соединения.
У TCP нет границ сообщений: один recv может вернуть часть запроса или несколько сообщений вместе. Нужен свой способ выделения сообщения — длина, разделитель или формат протокола.
Запись тоже бывает частичной. Неотправленный остаток сохраняют, а ожидание записи включают только при наличии данных. Иначе постоянно готовый к записи сокет может заставить цикл расходовать CPU впустую.
DefaultSelector выбирает доступный механизм платформы, но правила протокола и очистка соединений остаются задачей приложения.
#python #сети
Selector сообщил, что сокет доступен для чтения. Это означает, что можно попробовать прочитать данные, а не что весь запрос уже пришёл.
В разборе модуля selectors показывают небольшой цикл обработки соединений. Сокеты переводят в неблокирующий режим, а данные накапливают в буфере конкретного соединения.
У TCP нет границ сообщений: один recv может вернуть часть запроса или несколько сообщений вместе. Нужен свой способ выделения сообщения — длина, разделитель или формат протокола.
Запись тоже бывает частичной. Неотправленный остаток сохраняют, а ожидание записи включают только при наличии данных. Иначе постоянно готовый к записи сокет может заставить цикл расходовать CPU впустую.
DefaultSelector выбирает доступный механизм платформы, но правила протокола и очистка соединений остаются задачей приложения.
#python #сети
👍1
Таблицы из PDF: локальная библиотека или облачный API
Текст из PDF извлечён, а столбцы таблицы перемешались. Для отчёта важны не только слова, но и связи между строками, заголовками и ячейками.
В сравнении Docling и LlamaParse один документ обрабатывают двумя способами. Docling работает локально, LlamaParse отправляет PDF в облачный сервис. Отличаются установка, стоимость, форматы результата и возможности настройки.
Docling умеет отдавать таблицы в pandas DataFrame. Для облачного варианта нужно отдельно учитывать отправку документов и условия обработки данных.
Скорость авторы измеряют на одном десятистраничном PDF. Это пример эксперимента, а не универсальный рейтинг парсеров.
Для своего набора проверьте объединённые ячейки, многострочные заголовки, переносы таблиц между страницами и точность чисел после извлечения.
#python #данные
Текст из PDF извлечён, а столбцы таблицы перемешались. Для отчёта важны не только слова, но и связи между строками, заголовками и ячейками.
В сравнении Docling и LlamaParse один документ обрабатывают двумя способами. Docling работает локально, LlamaParse отправляет PDF в облачный сервис. Отличаются установка, стоимость, форматы результата и возможности настройки.
Docling умеет отдавать таблицы в pandas DataFrame. Для облачного варианта нужно отдельно учитывать отправку документов и условия обработки данных.
Скорость авторы измеряют на одном десятистраничном PDF. Это пример эксперимента, а не универсальный рейтинг парсеров.
Для своего набора проверьте объединённые ячейки, многострочные заголовки, переносы таблиц между страницами и точность чисел после извлечения.
#python #данные
👍1
Enum ограничивает состояния, но не проверяет переходы
Статус
В разборе Enum отдельно рассматривают значения для сериализации и имена членов.
Но наличие статусов NEW и PAID не запрещает переход обратно. Разрешённые переходы нужно описать отдельно, например в методе объекта или таблице правил.
Если значения уходят в API или базу, выбирайте их явно. Переименование элемента перечисления и изменение внешнего строкового значения могут иметь разные последствия для совместимости.
#python #архитектура
Статус
"paied" — допустимая строка. Enum позволяет проверить значение на границе приложения:from enum import Enum
class Status(Enum):
NEW = "new"
PAID = "paid"
print(Status("paid") is Status.PAID) # True
# Status("paied") вызовет ValueError
В разборе Enum отдельно рассматривают значения для сериализации и имена членов.
Status("paid") ищет по значению, а Status["PAID"] — по имени.Но наличие статусов NEW и PAID не запрещает переход обратно. Разрешённые переходы нужно описать отдельно, например в методе объекта или таблице правил.
Если значения уходят в API или базу, выбирайте их явно. Переименование элемента перечисления и изменение внешнего строкового значения могут иметь разные последствия для совместимости.
#python #архитектура
❤1
После GIL: почему одних потоков недостаточно
Убрать общую блокировку — не значит убрать гонки данных. Если несколько потоков меняют общие объекты, приложению по-прежнему нужны правила доступа.
На Python Language Summit обсуждали модель BOC: задачи заранее объявляют, какие защищённые данные им нужны, а планировщик координирует выполнение. Идея — перенести часть работы с блокировками из прикладного кода в механизм запуска задач.
Прототип bocpy использует отдельные интерпретаторы. Его уже можно исследовать, но полноценное владение объектами потребует изменений среды выполнения. Авторы также отмечают цену обмена данными.
Это исследовательское предложение, а не новая гарантия стандартного Python. Для рабочего приложения пока нужно явно выбирать модель параллельности и проверять совместное использование изменяемых объектов.
#python #параллельность
Убрать общую блокировку — не значит убрать гонки данных. Если несколько потоков меняют общие объекты, приложению по-прежнему нужны правила доступа.
На Python Language Summit обсуждали модель BOC: задачи заранее объявляют, какие защищённые данные им нужны, а планировщик координирует выполнение. Идея — перенести часть работы с блокировками из прикладного кода в механизм запуска задач.
Прототип bocpy использует отдельные интерпретаторы. Его уже можно исследовать, но полноценное владение объектами потребует изменений среды выполнения. Авторы также отмечают цену обмена данными.
Это исследовательское предложение, а не новая гарантия стандартного Python. Для рабочего приложения пока нужно явно выбирать модель параллельности и проверять совместное использование изменяемых объектов.
#python #параллельность
Как дать помощнику контекст ошибки из Logfire
Помощник видит код репозитория, но не знает, какой запрос завершился ошибкой и сколько времени заняла база. Без телеметрии он может уверенно искать причину не в том месте.
В разборе Logfire MCP показывают, как передать клиенту MCP доступ к трассам, логам и метрикам. Помощник может запросить данные через SQL, сопоставить ошибку с обработчиком и проверить гипотезу на реальном выполнении.
Начать расследование лучше с конкретного сервиса, интервала времени и проблемного запроса. Так проще получить проверяемый ответ и ограничить объём данных.
Права нужно выбирать по задаче: сервер предоставляет инструменты не только для запросов, но и для управления объектами мониторинга. Доступ к просмотру телеметрии сам по себе не требует разрешать изменения алертов или настроек.
#python #отладка
Помощник видит код репозитория, но не знает, какой запрос завершился ошибкой и сколько времени заняла база. Без телеметрии он может уверенно искать причину не в том месте.
В разборе Logfire MCP показывают, как передать клиенту MCP доступ к трассам, логам и метрикам. Помощник может запросить данные через SQL, сопоставить ошибку с обработчиком и проверить гипотезу на реальном выполнении.
Начать расследование лучше с конкретного сервиса, интервала времени и проблемного запроса. Так проще получить проверяемый ответ и ограничить объём данных.
Права нужно выбирать по задаче: сервер предоставляет инструменты не только для запросов, но и для управления объектами мониторинга. Доступ к просмотру телеметрии сам по себе не требует разрешать изменения алертов или настроек.
#python #отладка
Python 3.16 alpha: что уже может проверить автор библиотеки
Первая альфа Python 3.16 вышла 13 октября. Набор возможностей ещё меняется, но ждать финального выпуска для первой проверки совместимости необязательно.
В анонсе разработчики предлагают запускать библиотеки и приложения на предварительной версии и сообщать об ошибках CPython.
Для библиотеки полезно проверить установку, импорт, тесты и сборку расширений. Если установка не удалась, отделите несовместимость своего кода от отсутствия готовых сборок зависимостей.
Такую проверку можно добавить отдельным заданием CI, сохранив основную матрицу поддерживаемых версий. Сбой предварительной версии нужно разобрать, а не автоматически считать регрессией библиотеки.
Это ранний выпуск для тестирования. Перенос рабочего сервиса на него не требуется; финальный Python 3.16 запланирован на октябрь 2027 года.
#python #тестирование
Первая альфа Python 3.16 вышла 13 октября. Набор возможностей ещё меняется, но ждать финального выпуска для первой проверки совместимости необязательно.
В анонсе разработчики предлагают запускать библиотеки и приложения на предварительной версии и сообщать об ошибках CPython.
Для библиотеки полезно проверить установку, импорт, тесты и сборку расширений. Если установка не удалась, отделите несовместимость своего кода от отсутствия готовых сборок зависимостей.
Такую проверку можно добавить отдельным заданием CI, сохранив основную матрицу поддерживаемых версий. Сбой предварительной версии нужно разобрать, а не автоматически считать регрессией библиотеки.
Это ранний выпуск для тестирования. Перенос рабочего сервиса на него не требуется; финальный Python 3.16 запланирован на октябрь 2027 года.
#python #тестирование
Как найти медленную функцию новым профилировщиком Tachyon
Приложение тормозит, но непонятно, где оно проводит время. В Python 3.15 появился статистический профилировщик
В разборе Astral показывают запуск через uv:
Профилировщик периодически снимает состояние выполнения. Граф помогает найти участки, которые часто попадают в выборку, и выбрать место для дальнейшего исследования.
Число выборок не равно точному числу вызовов. А изменение короткой функции не обязательно ускорит весь сценарий.
После правки повторите тот же замер с теми же данными и отдельно сравните полное время работы. Авторское ускорение на одном примере нельзя переносить на любое приложение.
#python #производительность
Приложение тормозит, но непонятно, где оно проводит время. В Python 3.15 появился статистический профилировщик
profiling.sampling, известный как Tachyon.В разборе Astral показывают запуск через uv:
uv run --python 3.15 -m profiling.sampling run --flamegraph --browser app.py
Профилировщик периодически снимает состояние выполнения. Граф помогает найти участки, которые часто попадают в выборку, и выбрать место для дальнейшего исследования.
Число выборок не равно точному числу вызовов. А изменение короткой функции не обязательно ускорит весь сценарий.
После правки повторите тот же замер с теми же данными и отдельно сравните полное время работы. Авторское ускорение на одном примере нельзя переносить на любое приложение.
#python #производительность
❤1
Почему обновления Django важны даже без SQL-инъекций
Запрос может вредить серверу, просто заставляя его тратить слишком много памяти или процессорного времени на разбор данных.
В обновлении безопасности Django от 6 октября исправили несколько таких сценариев. Один связан с кешированием множества длинных языковых кодов, другой — с квадратичной сложностью разбора параметров HTTP-заголовка.
Исправления вошли в 6.1.2, 6.0.9 и 5.2.18. Обновляться нужно до актуального исправленного выпуска своей поддерживаемой ветки.
После обновления проверьте обработку необычных заголовков: внутри парсера изменился механизм разбора, поэтому некоторые некорректные значения могут обрабатываться иначе.
Общий урок для своего кода: ограничивать размер входа до дорогой обработки и помещения в кеш. Даже полезный кеш становится проблемой, если ключи бесконтрольно задаёт внешний запрос.
#python #django
Запрос может вредить серверу, просто заставляя его тратить слишком много памяти или процессорного времени на разбор данных.
В обновлении безопасности Django от 6 октября исправили несколько таких сценариев. Один связан с кешированием множества длинных языковых кодов, другой — с квадратичной сложностью разбора параметров HTTP-заголовка.
Исправления вошли в 6.1.2, 6.0.9 и 5.2.18. Обновляться нужно до актуального исправленного выпуска своей поддерживаемой ветки.
После обновления проверьте обработку необычных заголовков: внутри парсера изменился механизм разбора, поэтому некоторые некорректные значения могут обрабатываться иначе.
Общий урок для своего кода: ограничивать размер входа до дорогой обработки и помещения в кеш. Даже полезный кеш становится проблемой, если ключи бесконтрольно задаёт внешний запрос.
#python #django