shield защищает задачу, но не ожидание
Корутина ждёт важную операцию, и в этот момент её отменяют. Если ожидание обёрнуто в
Получаются два разных состояния: ожидающий уже отменён, операция ещё идёт. Создайте задачу явно и сохраните сильную ссылку на неё. Цикл событий держит только слабые ссылки, поэтому один вызов shield не заменяет управление сроком жизни фоновой работы.
shield также не защищает от прямого
Корутина ждёт важную операцию, и в этот момент её отменяют. Если ожидание обёрнуто в
asyncio.shield(task), внутренняя задача не отменяется вместе с вызывающей корутиной. Но у вызывающей корутины await всё равно поднимет CancelledError.Получаются два разных состояния: ожидающий уже отменён, операция ещё идёт. Создайте задачу явно и сохраните сильную ссылку на неё. Цикл событий держит только слабые ссылки, поэтому один вызов shield не заменяет управление сроком жизни фоновой работы.
shield также не защищает от прямого
task.cancel() и отмены из самой операции. В документации разобраны эти случаи. Заранее решите, кто дождётся задачи и обработает её результат. Отмена ожидания не означает, что операция завершилась.❤1
Пять секунд HTTPX не равны дедлайну запроса
Сервер может долго отдавать ответ маленькими порциями, а HTTPX не прервёт чтение по истечении пяти секунд с начала запроса. Тайм-аут чтения ограничивает ожидание очередного фрагмента данных. Если фрагменты приходят вовремя, суммарное чтение может длиться дольше.
У HTTPX четыре отдельных ограничения:
По умолчанию библиотека ограничивает сетевую неактивность пятью секундами. Настройки тайм-аутов позволяют задать эти ограничения отдельно. Если нужно ограничить общую длительность операции, задайте отдельный общий дедлайн с корректной отменой и освобождением ресурсов.
Сервер может долго отдавать ответ маленькими порциями, а HTTPX не прервёт чтение по истечении пяти секунд с начала запроса. Тайм-аут чтения ограничивает ожидание очередного фрагмента данных. Если фрагменты приходят вовремя, суммарное чтение может длиться дольше.
У HTTPX четыре отдельных ограничения:
connect, read, write и pool. Последнее относится к ожиданию свободного соединения в пуле. Поэтому PoolTimeout не исправляется одним увеличением времени подключения к серверу.По умолчанию библиотека ограничивает сетевую неактивность пятью секундами. Настройки тайм-аутов позволяют задать эти ограничения отдельно. Если нужно ограничить общую длительность операции, задайте отдельный общий дедлайн с корректной отменой и освобождением ресурсов.
❤1
После commit атрибут может потребовать SQL
В асинхронном коде обычное чтение ORM-атрибута не должно неожиданно ходить в базу. Но после
В руководстве SQLAlchemy 2.0 для AsyncSession используют
Это не предзагрузка всех связей и не гарантия свежести после чужой транзакции. Ленивую связь по-прежнему надо загрузить явным способом. Для параллельных задач всё равно нужны отдельные AsyncSession.
В асинхронном коде обычное чтение ORM-атрибута не должно неожиданно ходить в базу. Но после
commit() SQLAlchemy по умолчанию помечает состояние объектов как устаревшее. Следующее обращение к полю может попытаться загрузить его заново, уже вне явного await.В руководстве SQLAlchemy 2.0 для AsyncSession используют
expire_on_commit=False. Уже загруженные значения остаются доступны после commit. Нужное поле или связь можно обновить явно через await session.refresh(obj, ["field"]).Это не предзагрузка всех связей и не гарантия свежести после чужой транзакции. Ленивую связь по-прежнему надо загрузить явным способом. Для параллельных задач всё равно нужны отдельные AsyncSession.
Исправление Ruff может сменить исключение
Замена
Первое выражение поднимет
По умолчанию Ruff применяет safe fixes. Флаг
Замена
list(values)[0] на next(iter(values)) позволяет получить первый элемент без построения всего списка. Но на пустом входе меняется тип исключения.Первое выражение поднимет
IndexError, второе StopIteration. Обработчик except IndexError больше не сработает. Именно поэтому исправление правила RUF015 в документации Ruff относится к unsafe, хотя на непустом входе оно решает ту же задачу.По умолчанию Ruff применяет safe fixes. Флаг
ruff check --fix --unsafe-fixes разрешает и изменения, способные повлиять на поведение или удалить комментарии. Перед таким запуском стоит проверить пустые входы и обработчики ошибок. Ускорение из примера в документации нельзя переносить на любой код.👍2
asdict копирует глубже, чем кажется
Вызов
Если поле содержит большой список, рассчитывать на сохранение ссылки на него нельзя. Для поверхностного представления документация предлагает собрать словарь через
Для чтения полей без копирования вложенных объектов подходит поверхностный словарь. Если нужно менять вложенный список независимо от dataclass, он не подойдёт: вложенные данные остаются общими. Ни один из этих способов сам по себе не превращает произвольное содержимое полей в готовый JSON.
Вызов
asdict(obj) не ограничивается созданием словаря полей dataclass. Функция рекурсивно обходит вложенные dataclass, словари, списки и кортежи, а прочие объекты копирует через copy.deepcopy.Если поле содержит большой список, рассчитывать на сохранение ссылки на него нельзя. Для поверхностного представления документация предлагает собрать словарь через
fields() и getattr(). На карточке видно различие: у такой сборки вложенный список остаётся общим с исходным объектом.Для чтения полей без копирования вложенных объектов подходит поверхностный словарь. Если нужно менять вложенный список независимо от dataclass, он не подойдёт: вложенные данные остаются общими. Ни один из этих способов сам по себе не превращает произвольное содержимое полей в готовый JSON.
fileno может отправить маленький файл на диск
Даже если в
У этого временного файла несколько причин перехода к дисковому файлу. При положительном лимите это превышение
Лимит здесь полезен для буферизации, но условие «размер меньше порога» не доказывает отсутствия файлового I/O. При этом слово «диск» описывает файловое поведение API и не указывает на конкретный физический носитель или задержку операционной системы.
Даже если в
SpooledTemporaryFile(max_size=1_000_000) записана всего сотня байт, запрос файлового дескриптора перенесёт содержимое из памяти в дисковый файл.У этого временного файла несколько причин перехода к дисковому файлу. При положительном лимите это превышение
max_size. Вызов fileno() делает то же самое независимо от размера, а rollover() явно запускает этот переход. Поэтому библиотека, которой передали file-like объект, может изменить способ хранения одним запросом дескриптора.Лимит здесь полезен для буферизации, но условие «размер меньше порога» не доказывает отсутствия файлового I/O. При этом слово «диск» описывает файловое поведение API и не указывает на конкретный физический носитель или задержку операционной системы.
🆒2
Где Hypothesis хранит найденные сбои
Hypothesis нашёл неудачный вход, а следующий запуск будет уже на новой машине. Будет ли пример проверен снова? Это зависит в том числе от базы примеров: она сохраняет провалившиеся случаи, а фаза
В обычной конфигурации используется
Проверьте активный профиль и срок жизни хранилища CI-раннера. База ускоряет повтор известных сбоев, но не заменяет регрессионный тест. Важный вход закрепите через
Hypothesis нашёл неудачный вход, а следующий запуск будет уже на новой машине. Будет ли пример проверен снова? Это зависит в том числе от базы примеров: она сохраняет провалившиеся случаи, а фаза
reuse загружает их в следующих запусках.В обычной конфигурации используется
.hypothesis/examples. Если каталог недоступен для чтения или записи, библиотека предупреждает и переходит к базе в памяти. При database=None хранения нет вообще. В текущем встроенном профиле ci задано именно это значение, так что постоянный кеш в CI нельзя считать включённым автоматически.Проверьте активный профиль и срок жизни хранилища CI-раннера. База ускоряет повтор известных сбоев, но не заменяет регрессионный тест. Важный вход закрепите через
@example или отдельный тест, а не оставляйте только в каталоге кеша.⚡1
Путь к ресурсу пакета может быть временным
Ресурс установленного пакета не обязательно лежит обычным файлом рядом с модулем. Пакет может читаться из zip-архива, а
Для чтения текста часто достаточно
Поэтому передавайте путь потребителю внутри блока, пока ресурс нужен. Не сохраняйте его для отложенного чтения после выхода. Очистка касается созданного временного файла: если ресурс уже лежал на диске, исходный файл пакета при закрытии контекста не удаляется.
Ресурс установленного пакета не обязательно лежит обычным файлом рядом с модулем. Пакет может читаться из zip-архива, а
importlib.resources.files() возвращает объект Traversable, без гарантии, что ресурс лежит на диске.Для чтения текста часто достаточно
read_text(). Если стороннему API нужен настоящий pathlib.Path, используйте as_file(resource) как контекстный менеджер. При необходимости он извлечёт ресурс во временный файл и удалит его при выходе из with.Поэтому передавайте путь потребителю внутри блока, пока ресурс нужен. Не сохраняйте его для отложенного чтения после выхода. Очистка касается созданного временного файла: если ресурс уже лежал на диске, исходный файл пакета при закрытии контекста не удаляется.
🤔2👍1
Обрезать строку и не оторвать ударение
Одна видимая буква может состоять из нескольких кодовых точек. При сокращении подписи в интерфейсе срез по произвольному индексу может отделить комбинируемый знак от буквы.
В Python 3.15 появился итератор графемных кластеров
Можно выбрать целые кластеры и по их границам сформировать сокращённую подпись. При этом число графем не определяет ширину текста: для выравнивания колонок терминала или расчёта пикселей всё ещё нужен отдельный способ измерения.
Одна видимая буква может состоять из нескольких кодовых точек. При сокращении подписи в интерфейсе срез по произвольному индексу может отделить комбинируемый знак от буквы.
В Python 3.15 появился итератор графемных кластеров
unicodedata.iter_graphemes. Он использует расширенные правила сегментации Unicode UAX #29. У каждого элемента есть границы start и end, а преобразование в строку возвращает сам кластер.Можно выбрать целые кластеры и по их границам сформировать сокращённую подпись. При этом число графем не определяет ширину текста: для выравнивания колонок терминала или расчёта пикселей всё ещё нужен отдельный способ измерения.
✍2
Куда пропало условие Windows в pylock.toml
Зависимость нужна только в Windows и только группе разработки. В
Именно такую ошибку исправили в Pipenv 2026.10.1. Она затрагивала маркеры, которые вместе с ограничением платформы или версии Python содержали
Если вы экспортируете зависимости в
Зависимость нужна только в Windows и только группе разработки. В
pylock.toml это можно записать одним маркером с обоими условиями. Если при чтении потерять весь маркер, пакет начнёт устанавливаться и на других платформах.Именно такую ошибку исправили в Pipenv 2026.10.1. Она затрагивала маркеры, которые вместе с ограничением платформы или версии Python содержали
dependency_groups. В журнале приведён пример файла, экспортированного через PDM. При обработке группы Pipenv терял и оставшуюся часть условия.Если вы экспортируете зависимости в
pylock.toml, а затем устанавливаете их через Pipenv, проверьте комбинированные маркеры на разных целевых окружениях.❤1
Передать накопленные байты и опустошить буфер
Парсер накапливает данные в изменяемом
Согласно документации, в CPython извлечение всех байтов выполняется без копирования. Если взять только префикс и сохранить остаток в
Если остаток вам не нужен, документация предлагает сначала обрезать буфер, затем забрать его целиком. При последовательном разборе сообщений, где хвост ещё понадобится, извлечь префикс без копирования не получится.
Парсер накапливает данные в изменяемом
bytearray, а наружу должен отдать неизменяемый bytes. В Python 3.15 у буфера появился метод take_bytes: он извлекает первые n байтов, а без размера забирает всё содержимое и оставляет буфер пустым.Согласно документации, в CPython извлечение всех байтов выполняется без копирования. Если взять только префикс и сохранить остаток в
bytearray, копирование потребуется.Если остаток вам не нужен, документация предлагает сначала обрезать буфер, затем забрать его целиком. При последовательном разборе сообщений, где хвост ещё понадобится, извлечь префикс без копирования не получится.
pypdf ограничил размер таблицы перекрёстных ссылок PDF
В pypdf 6.21.2 два исправления вошли в раздел Security: библиотека избегает повторных загрузок файла целиком и ограничивает размер стандартной таблицы перекрёстных ссылок
Численный предел, серьёзность проблем и условия их эксплуатации в записи релиза не указаны. По ней нельзя определить безопасный максимальный размер документа. Обновление также не даёт оснований считать любой PDF безвредным.
Если ваш сервис читает пользовательские PDF через pypdf, учитывайте эти исправления при выборе версии зависимости. Ограничения времени и памяти обработчика задавайте отдельно: изменения внутри парсера не устанавливают общий бюджет ресурсов процесса.
В pypdf 6.21.2 два исправления вошли в раздел Security: библиотека избегает повторных загрузок файла целиком и ограничивает размер стандартной таблицы перекрёстных ссылок
xref.Численный предел, серьёзность проблем и условия их эксплуатации в записи релиза не указаны. По ней нельзя определить безопасный максимальный размер документа. Обновление также не даёт оснований считать любой PDF безвредным.
Если ваш сервис читает пользовательские PDF через pypdf, учитывайте эти исправления при выборе версии зависимости. Ограничения времени и памяти обработчика задавайте отдельно: изменения внутри парсера не устанавливают общий бюджет ресурсов процесса.
Counter вычисляет разницу между количествами
Два набора деталей содержат одни и те же названия, но в разных количествах. Если превратить их в множества, различие пропадёт. Для такой сверки в Python 3.15 добавили симметрическую разность
Для каждого ключа операция берёт максимум минус минимум из двух счётчиков. Поэтому разница между тремя и одной деталью сохраняется как две единицы. Равные количества дают ноль, и такого ключа в результате не будет. Направление расхождения теряется: по результату нельзя сказать, в каком наборе деталей больше.
Операция принимает и отрицательные значения счётчиков. Максимум и минимум берутся из исходных значений, без предварительного обнуления отрицательных. Как и другие операции мультимножеств
Два набора деталей содержат одни и те же названия, но в разных количествах. Если превратить их в множества, различие пропадёт. Для такой сверки в Python 3.15 добавили симметрическую разность
Counter, оператор ^.Для каждого ключа операция берёт максимум минус минимум из двух счётчиков. Поэтому разница между тремя и одной деталью сохраняется как две единицы. Равные количества дают ноль, и такого ключа в результате не будет. Направление расхождения теряется: по результату нельзя сказать, в каком наборе деталей больше.
Операция принимает и отрицательные значения счётчиков. Максимум и минимум берутся из исходных значений, без предварительного обнуления отрицательных. Как и другие операции мультимножеств
Counter, она оставляет в результате только положительные количества.👍1
Одинаковое имя XMP-тега ещё не означает одно поле
В метаданных изображения могут встретиться XML-теги с одинаковым локальным именем из разных пространств имён. Если убрать URI пространства, различить такие свойства по одному имени уже не получится.
В Pillow 13.0.0 метод
Если вам нужно различать свойства из разных пространств имён, выбирайте
В метаданных изображения могут встретиться XML-теги с одинаковым локальным именем из разных пространств имён. Если убрать URI пространства, различить такие свойства по одному имени уже не получится.
В Pillow 13.0.0 метод
Image.getxmp получил аргумент strip_namespaces. По умолчанию он равен True, и библиотека по-прежнему убирает URI. Значение False сохраняет полное имя тега в форме {namespace-uri}local-name.Если вам нужно различать свойства из разных пространств имён, выбирайте
False и учитывайте полные ключи при чтении результата. Опция меняет только представление имён XMP-тегов.Фильтры предупреждений в CLI научились понимать регулярки
В CI бывает нужно превратить в ошибку конкретное семейство предупреждений и оставить остальные видимыми. Настройку для дочернего процесса удобно передать через
Начиная с Python 3.15 поля сообщения и модуля поддерживают регулярные выражения, если поле начинается и заканчивается косой чертой. Без этих разделителей сохраняется буквальное сопоставление. Это дополнение к синтаксису фильтра, его действия и категории остаются прежними.
У полей разные правила. Сообщение сопоставляется с начала без учёта регистра. Имя модуля учитывает регистр: буквальная строка должна совпасть целиком, а регулярное выражение проверяет начало полного имени. Поэтому одинаковый шаблон в этих двух полях может охватить разные предупреждения.
В CI бывает нужно превратить в ошибку конкретное семейство предупреждений и оставить остальные видимыми. Настройку для дочернего процесса удобно передать через
-W или PYTHONWARNINGS, без правок приложения.Начиная с Python 3.15 поля сообщения и модуля поддерживают регулярные выражения, если поле начинается и заканчивается косой чертой. Без этих разделителей сохраняется буквальное сопоставление. Это дополнение к синтаксису фильтра, его действия и категории остаются прежними.
У полей разные правила. Сообщение сопоставляется с начала без учёта регистра. Имя модуля учитывает регистр: буквальная строка должна совпасть целиком, а регулярное выражение проверяет начало полного имени. Поэтому одинаковый шаблон в этих двух полях может охватить разные предупреждения.
wxPython 4.3.2 добавил wheels для Python 3.15 и проверку типов обработчиков Bind
При переходе Python-приложения с нативным GUI на новый интерпретатор нужны и подходящие бинарные сборки GUI-библиотеки. В wxPython 4.3.2 заявлены официальная поддержка Python 3.15 и сборка wheels для него. Релиз использует wxWidgets 3.3.4. Выпуск Windows wheels для 32-битной архитектуры прекращён.
Сгенерированные
Типизатор сможет найти часть ошибок при подключении событий до запуска окна. Работу виджетов в вашей ОС нужно проверять отдельно. Перед миграцией проверьте наличие подходящего wheel и поведение GUI на целевой платформе.
При переходе Python-приложения с нативным GUI на новый интерпретатор нужны и подходящие бинарные сборки GUI-библиотеки. В wxPython 4.3.2 заявлены официальная поддержка Python 3.15 и сборка wheels для него. Релиз использует wxWidgets 3.3.4. Выпуск Windows wheels для 32-битной архитектуры прекращён.
Сгенерированные
.pyi теперь позволяют проверять типы обработчиков, передаваемых в Bind. Среди других правок в stubs — представление enum в виде классов и более полное описание методов и типов.Типизатор сможет найти часть ошибок при подключении событий до запуска окна. Работу виджетов в вашей ОС нужно проверять отдельно. Перед миграцией проверьте наличие подходящего wheel и поведение GUI на целевой платформе.
Decimal в тайм-ауте не делает ожидание точнее
Тайм-аут может прийти в программу как
В описании изменения отдельно оговорено: точность от этого не повышается. Изменение позволяет передавать уже вычисленное значение без преобразования на стороне вызывающего кода.
Что именно ограничивает тайм-аут и когда функция возвращает управление, по-прежнему зависит от её контракта. Допустимый числовой тип этих правил не меняет.
Тайм-аут может прийти в программу как
Decimal из конфигурации или как Fraction после вычисления. В Python 3.15 функции с аргументами timestamp и timeout принимают любые вещественные числа, а не только int и float.В описании изменения отдельно оговорено: точность от этого не повышается. Изменение позволяет передавать уже вычисленное значение без преобразования на стороне вызывающего кода.
Что именно ограничивает тайм-аут и когда функция возвращает управление, по-прежнему зависит от её контракта. Допустимый числовой тип этих правил не меняет.
❤1
Стартовый код пакета переезжает из .pth в .start
Файл
В Python 3.15 PEP 829 вводит файлы
Если рядом есть одноимённый
Файл
.pth может не только расширять sys.path. При запуске Python модуль site исполняет найденные в нём строки, начинающиеся с import. Этот код выполняется ещё до первой строки приложения.В Python 3.15 PEP 829 вводит файлы
.start с явными точками входа в форме pkg.mod:callable. Функция вызывается без аргументов, возвращённое значение отбрасывается. У PEP статус Final.Если рядом есть одноимённый
.start, строки import из соответствующего .pth игнорируются. Добавление путей из .pth сохраняется. Это позволяет переносить стартовую инициализацию отдельно от настройки путей, сохраняя старый файл для прежних интерпретаторов.Обновление Python не обновляет pip в старых venv
В Python 3.15.1 обновили комплектный pip до 26.2.2. В его состав входит certifi 2026.10.19 с изменениями после инцидента с центрами сертификации eMudhra / emSign. Но установка нового интерпретатора сама по себе не обновляет инструменты внутри уже созданных виртуальных окружений.
На странице релиза отдельно просят обновить pip и uv в существующих venv до последних версий. Там же приведены ссылка на wheel pip с SHA-256 и отдельная инструкция по обновлению сертификатов для установки на macOS.
Проверяйте версию pip внутри нужного окружения. Версия системного Python этого не показывает. Для обновления сертификатов выбирайте инструкции релиза, относящиеся к вашему способу установки.
В Python 3.15.1 обновили комплектный pip до 26.2.2. В его состав входит certifi 2026.10.19 с изменениями после инцидента с центрами сертификации eMudhra / emSign. Но установка нового интерпретатора сама по себе не обновляет инструменты внутри уже созданных виртуальных окружений.
На странице релиза отдельно просят обновить pip и uv в существующих venv до последних версий. Там же приведены ссылка на wheel pip с SHA-256 и отдельная инструкция по обновлению сертификатов для установки на macOS.
Проверяйте версию pip внутри нужного окружения. Версия системного Python этого не показывает. Для обновления сертификатов выбирайте инструкции релиза, относящиеся к вашему способу установки.
❤1
Unicode-идентификатор начинается и продолжается по разным правилам
Если вы пишете токенизатор или подсветку для языка с Unicode-именами, проверки «это буква или цифра» может оказаться недостаточно. У Unicode есть отдельные свойства для начальной и последующих позиций идентификатора.
В Python 3.15 эти проверки добавили в
Так можно проверять свойства символов без собственного списка диапазонов, который придётся обновлять вместе с Unicode. Для проверки целого имени нужны ещё правила конкретного языка. Например, эти функции не проверяют, является ли имя зарезервированным словом.
Если вы пишете токенизатор или подсветку для языка с Unicode-именами, проверки «это буква или цифра» может оказаться недостаточно. У Unicode есть отдельные свойства для начальной и последующих позиций идентификатора.
В Python 3.15 эти проверки добавили в
unicodedata. Функция isxidstart проверяет свойство XID_Start, а isxidcontinue — XID_Continue по UAX #31. Каждая принимает один символ. Модуль использует базу Unicode 17.0.0.Так можно проверять свойства символов без собственного списка диапазонов, который придётся обновлять вместе с Unicode. Для проверки целого имени нужны ещё правила конкретного языка. Например, эти функции не проверяют, является ли имя зарезервированным словом.