Python 3.10 теряет поддержку в октябре 2026 года: как найти забытые скрипты и обновить автоматизацию

Скрипт на Python запускается ночью и переносит данные между системами. Кто его писал, уже не помнят. Перед окончанием поддержки Python 3.10 риск здесь не в самой цифре версии, а в том, что никто не знает зависимости и не проверяет результат задания.

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

Инвентаризация Python-скриптов, зависимостей, тестов и поэтапного перехода на поддерживаемую версию
Содержание 14 разделов

Реестр Python-задач и план миграции без остановки бизнес-процессов

Ветка Python 3.10 переходит в статус end-of-life в октябре 2026 года — точный день Python Software Foundation в официальном графике не публикует, указан только месяц [1][2]. После этого для 3.10 перестанут выходить исправления безопасности. Проблема обычно не в главном приложении компании, а в фоновых скриптах — ботах, парсерах, cron-задачах и старых контейнерах, у которых часто нет явного владельца. Разберём, как их найти, как проверить на совместимость с новой версией интерпретатора и как перейти на неё без сюрпризов в продакшене.

Почему это не абстрактная проблема

Когда компания слышит «Python N.N теряет поддержку», первая мысль — «у нас всё на актуальной версии, это не про нас». На практике под контролем DevOps и разработки обычно находится основное приложение: сайт, API, бэкенд. А вот скрипт, который раз в ночь выгружает остатки со склада в 1С, бот в Telegram, написанный стажёром два года назад, или парсер прайс-листов конкурентов — живут своей жизнью на отдельном сервере или в закреплённом за ушедшим сотрудником контейнере. Именно там чаще всего и остаётся Python 3.10, потому что там его никто не трогал с момента установки.

После окончания поддержки такой скрипт не остановится сам — он продолжит работать. Но перестанет получать патчи безопасности от PSF, а значит, любая новая уязвимость в интерпретаторе или его стандартной библиотеке останется неисправленной [1]. Дополнительно начинают рваться косвенные связи: библиотеки перестают тестировать свой код против 3.10, облачные платформы и managed-сервисы отключают runtime на этой версии, а базовые Docker-образы вроде python:3.10-alpine перестают получать обновления вскоре после даты EOL [2].

Статья полезна тем, кто отвечает за инфраструктуру, DevOps-процессы или ИТ-аудит в компаниях с собственной автоматизацией на Python — ETL-пайплайнами, ботами, интеграциями с 1С, CRM или внешними API.

Что на самом деле значит «конец поддержки» и когда он наступит

Жизненный цикл каждой ветки Python описан в PEP 602 и фиксируется в официальной таблице статусов на devguide.python.org. Согласно ей, ветка 3.10 сейчас в фазе security (только патчи безопасности, без новых бинарных сборок), и её End of life обозначен как «2026-10» курсивом — то есть это плановая, а не жёстко зафиксированная дата, указан только месяц [1].

Карта автоматизации: Найти скрипт → Назначить владельца → Записать зависимости
Карта автоматизации: Найти скрипт, Назначить владельца, Записать зависимости.

Здесь важно не подменять источники: часть индустриальных разборов и вендорских блогов называет точную дату — 31 октября 2026 года [2][4], и в сообществе Python даже возникал отдельный вопрос, есть ли у PSF официально утверждённый день [3]. Но сам официальный график CPython такой точности не даёт — там указан только месяц [1]. Для планирования это означает практический вывод: ориентироваться нужно на «конец октября 2026 года» как на крайний срок, не называя конкретное число как гарантированное PSF, и закладывать запас в несколько недель до этой границы.

Полезно понимать контекст: Python 3.9 уже прошёл EOL в октябре 2025 года, а Python 3.8 — в октябре 2024-го [2]. То есть 3.10 — это не первая, а третья волна подобной миграции подряд, и опыт предыдущих волн показывает: компании, которые откладывали переход, к моменту дедлайна ещё не завершили миграцию с предыдущей версии [2].

Как устроен жизненный цикл Python-релиза

Каждая ветка CPython проходит пять фаз: feature (принимаются новые возможности), prerelease, bugfix (стабильный релиз, патчи и фиксы каждые два месяца), security (только исправления безопасности, новых бинарных сборок больше нет) и, наконец, end-of-life, когда ветка замораживается полностью [1]. Ветка 3.10 была выпущена в октябре 2021 года и провела в фазе security около двух лет — это стандартный интервал по PEP 602 [1].

Практическое следствие: если сегодня скрипт использует Python 3.10, то целевой версией для миграции разумно выбирать не «любую более новую», а ту, у которой запас поддержки максимален и совместимость с текущими зависимостями наименее рискованна — как правило, это 3.12 или 3.13 [2].

Российская специфика: сертифицированные ОС и репозитории

Для компаний, которые используют сертифицированные операционные системы — например, Astra Linux, — ситуация немного отличается от «обычного» Linux-сервера. Python в таких дистрибутивах устанавливается по умолчанию, но версия, доступная через официальный репозиторий, привязана к версии самой ОС и не всегда совпадает с актуальной веткой CPython [12]. Так, в Astra Linux Common Edition отдельным метапакетом добавлялась версия Python 3.7 — то есть организации, работающие на сертифицированных сборках, могут обнаружить, что «из коробки» им доступна версия куда старше даже уходящей 3.10 [13].

Это значит, что план миграции для инфраструктуры на отечественных дистрибутивах нужно продумывать отдельно: собирать более новый интерпретатор из исходников или через расширенный репозиторий, проверять, требует ли добавление стороннего компонента отдельного прохождения аттестации (этот вопрос типично возникает при добавлении внешних пакетов на аттестованных системах), и закладывать время на согласование с ИБ-службой. Если автоматизация обрабатывает персональные данные — например, интеграции с CRM, 1С или внешними формами сбора данных, — обновление окружения стоит проводить одновременно с проверкой того, что состав интеграций и потоков данных вообще известен и задокументирован, чтобы не потерять из виду цепочку обработки ПДн при смене версии интерпретатора.

Как найти все Python-автоматизации в компании

Прежде чем что-то мигрировать, нужно понять, что вообще существует. Задача разбивается на три технических слоя.

Проверка окружения: Версия Python → Пакеты → Пробный запуск
Проверка окружения: Версия Python, Пакеты, Пробный запуск.

Интерпретаторы и виртуальные окружения. Стандартные инструменты вроде venv и virtualenv не хранят единый реестр созданных окружений — их приходится искать по файловой системе [11]. Практический подход: искать директории с характерным маркером — файлом активации (bin/activate) или структурой pyvenv.cfg, а не полагаться на угадывание имён папок [11]. Отдельно стоит проверить типовые места вроде ~/.virtualenvs, ~/.pyenv/versions, а также поискать все бинарники python* в $PATH и символические ссылки на них — это даёт более полную картину, чем проверка одного «системного» интерпретатора [11].

Контейнеры и образы. Нужно пройтись по всем Docker/Podman-образам в реестре и локальных хостах и проверить базовый образ (FROM python:3.10-...) и версию, зафиксированную в Dockerfile или в манифестах Kubernetes/Compose. Отдельная категория риска — образы, которые никто давно не пересобирал: если CI не запускался месяцами, зафиксированная версия интерпретатора могла остаться той же, даже если Dockerfile формально ссылается на «актуальную» ветку через тег вида 3.10-slim.

Cron, systemd-таймеры и планировщики. Это самая скрытая часть: crontab отдельного пользователя не виден администратору по умолчанию, а systemd-таймеры и службы разбросаны по конфигурациям сервисов. Здесь нет единого «идеального» инструмента — практика сводится к системному обходу: список всех пользовательских crontab на каждом сервере, список systemd-таймеров и служб, а также ревизия задач в внешних планировщиках (Airflow, Cron в CI/CD, задачи в PaaS-платформах). Каждую найденную задачу стоит сразу же дополнить пометкой: какой интерпретатор она вызывает и по какому пути.

Результат этого шага — не список выводов в терминале, а зафиксированный реестр: путь к интерпретатору или окружению, где оно физически находится (сервер, контейнер, облачный проект), какая версия Python, и какой файл или задача его использует.

Как определить владельца скрипта и бизнес-процесс

Технический реестр бесполезен без ответа на вопрос «зачем это работает и кто отвечает за результат». Здесь помогает несколько источников, которые редко проверяют одновременно:

  • история изменений в системе контроля версий — кто и когда последний раз коммитил в этот код;
  • метаданные мониторинга и алертинга — если задача на что-то жалуется в чат или дашборд, у алерта обычно есть ответственный канал или тег команды;
  • журналы выполнения самой задачи — по логам часто видно, какие системы она читает и куда пишет, что указывает на бизнес-процесс даже при отсутствии документации;
  • прямой разговор с командами — часто самый быстрый способ выяснить, что скрипт вообще существует и зачем, особенно если он был написан подрядчиком или сотрудником, который уже покинул компанию.

Если ни один из источников не даёт ответа, а сама задача формально продолжает работать без ошибок, — это тревожный сигнал, а не повод её игнорировать: непрозрачная зависимость от неизвестного процесса — ровно та ситуация, где миграция интерпретатора без анализа может незаметно сломать что-то важное для бизнеса.

Как проверить зависимости и совместимость с целевым интерпретатором

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

Безопасный переход: Стенд → Сверка данных → Рабочее задание
Безопасный переход: Стенд, Сверка данных, Рабочее задание.

Устаревшие и удалённые модули стандартной библиотеки. Модуль distutils был официально признан устаревшим ещё в Python 3.10 и полностью удалён в Python 3.12 — последней версией, где он ещё присутствовал, была 3.11 [5][6]. Если код или его зависимости (например, старые сборочные скрипты) используют import distutils, при переходе на 3.12+ это приведёт к прямой ошибке импорта, и потребуется переход на setuptools или sysconfig [5][6]. Кроме того, PEP 594 описывает целый список так называемых «мёртвых батареек» — модулей вроде cgi, smtpd, asyncore, asynchat, imghdr, telnetlib, которые были помечены устаревшими в 3.11 и физически удалены из стандартной библиотеки в Python 3.13 [7][8]. Если старый ETL-скрипт когда-то использовал, например, cgi для парсинга форм или smtpd для локального почтового сервера, на 3.13 он не запустится без замены этих модулей на современные аналоги [7][8]. Отдельно стоит проверить код на неявную зависимость от кодировки по умолчанию: начиная с Python 3.15 планируется включить UTF-8-режим по умолчанию для операций чтения и записи текста без явно указанной кодировки — это в первую очередь касается кода, который полагался на системную локаль, особенно на Windows и в средах с локалью C/POSIX, к которым относятся многие контейнеры и cron-окружения [9].

Нативные расширения и совместимость по ABI. Если автоматизация использует библиотеки с C-расширениями (например, для парсинга, работы с числами или криптографией), важно проверить не только номер версии пакета, но и то, есть ли для целевой версии Python готовый бинарный wheel. Имя wheel-файла кодирует версию интерпретатора, ABI и платформу (например, тег cp312 означает сборку под CPython 3.12) [16]. Стандарт manylinux позволяет одному бинарному пакету работать на разных дистрибутивах Linux за счёт линковки против заранее оговорённого минимального набора системных библиотек [14]. Но на практике заявленная в имени пакета совместимость по «стабильному ABI» не всегда подтверждается фактическим поведением сборки — независимый разбор показал, что часть пакетов, помеченных как ABI3-совместимые, в реальности такими не являются [15]. Поэтому для критичных зависимостей с нативным кодом стоит не просто устанавливать пакет на целевой версии Python, а прогонять полноценные тесты именно на этой версии, а не полагаться на успешную установку через pip как на подтверждение совместимости.

Как зафиксировать зависимости и воспроизвести окружение на стенде

Вывод pip freeze часто путают с полноценным описанием зависимостей проекта — на деле это просто снимок того, что установлено в окружении прямо сейчас, включая посторонние пакеты, случайно попавшие туда за время работы над проектом. Для чистой миграции полезно сначала понять, какие зависимости — прямые, а какие подтянуты транзитивно; для этого используют инструменты построения дерева зависимостей, а не читают плоский список руками.

Дальше стоит:

  1. Зафиксировать точные версии всех прямых и транзитивных зависимостей в lock-файле (через pip-tools, poetry или аналог), а не оставлять диапазоны версий вида >=.
  2. Проверить эти зависимости на известные уязвимости — для этого есть специализированный инструмент pip-audit, который сверяет установленные версии пакетов с базой рекомендаций по безопасности Python-пакетов [10].
  3. Развернуть отдельный стенд с целевой версией интерпретатора (контейнер или изолированное окружение), установить туда зафиксированные зависимости и убедиться, что сама установка проходит без ошибок сборки нативных расширений.
  4. Только после успешной установки переходить к функциональному тестированию — установка без ошибок ещё не означает корректность результата выполнения.

Как сравнить результаты обработки данных на контрольных данных

Успешный запуск скрипта на новой версии Python — не то же самое, что идентичный результат. Смена интерпретатора и версий зависимостей может незаметно изменить поведение в нескольких типичных местах:

После обновления: Журнал ошибок → Результат задания → План возврата
После обновления: Журнал ошибок, Результат задания, План возврата.
  • Кодировки. Если код читает или пишет файлы без явного указания encoding=, поведение может отличаться между операционными системами и версиями Python — особенно с учётом курса на UTF-8-режим по умолчанию в будущих версиях [9]. Стоит явно искать в коде все вызовы open() без указанной кодировки и добавлять её явно, а не полагаться на поведение по умолчанию.
  • Даты и время. Изменения в обработке часовых поясов, локалей или форматов дат между библиотеками часто проявляются только на граничных значениях — начале и конце месяца, переходе на летнее время, недокументированных региональных форматах.
  • Денежные значения. Округление, работа с типом Decimal против float, поведение при делении — это места, где визуально «рабочий» скрипт может тихо начать округлять на копейку иначе.
  • Обработка файлов. Различия в поведении библиотек парсинга (CSV, Excel, XML) между версиями иногда меняют то, как обрабатываются пустые ячейки, спецсимволы или повреждённые строки.

Практический метод проверки — не «прогнать и посмотреть, что не упало», а подготовить набор контрольных входных данных, заранее сохранить эталонный результат обработки на старой версии интерпретатора, и затем побайтово или построчно сравнить результат обработки этих же данных на новой версии. Такой подход часто называют snapshot- или golden-file-тестированием, и он ловит именно тихие расхождения, а не только явные падения с ошибкой.

Как обновить задания и мониторинг

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

  • путь к интерпретатору в самой cron-записи или systemd-юните — старые задачи часто жёстко прописывают полный путь вида /usr/bin/python3.10, и смена версии в системе сама по себе ничего не меняет, пока путь не обновлён вручную;
  • Dockerfile и базовые образы — с фиксацией новой версии тегом, а не общим latest, чтобы избежать повторения той же проблемы через несколько лет;
  • зависимости CI/CD-конвейеров — матрицу версий для тестов, чтобы новые изменения в коде сразу проверялись против целевой версии интерпретатора;
  • правила мониторинга и алертинга — если задача мониторится по логам или коду завершения, стоит убедиться, что после миграции алерты по-прежнему привязаны к правильному процессу, а не к артефактам старого окружения (например, к пути внутри старого venv).

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

Ограничения, ошибки и риски

Наиболее частые ошибки при подобной миграции:

  • Удаление старого интерпретатора или окружения сразу после того, как «вроде заработало» на новой версии — прежде чем это делать, стоит убедиться, что абсолютно все зависимые задачи, включая редко запускающиеся (например, ежемесячные или квартальные отчёты), успешно проверены на новом окружении.
  • Обновление только «видимых» скриптов и игнорирование фоновых задач без владельца — именно они чаще всего остаются на устаревшей версии дольше всего.
  • Полагание на успешную установку зависимостей как на доказательство совместимости, без реального прогона на контрольных данных.
  • Игнорирование специфики сертифицированных ОС — попытка установить актуальную версию Python способом, не совместимым с политикой обновлений аттестованной системы.

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

Вывод

Дедлайн октября 2026 года сам по себе не остановит работающие скрипты на Python 3.10 — но с этого момента любые новые уязвимости в интерпретаторе останутся без официальных патчей [1]. Главная практическая задача — не «обновить Python», а сначала увидеть всю картину: составить реестр всех интерпретаторов, окружений и заданий, определить их владельцев, проверить зависимости на совместимость с целевой версией и убедиться, что результат обработки данных не изменился на контрольном наборе. Только после этого имеет смысл переключать продакшен-задачи и обновлять мониторинг — и лишь затем окончательно выводить из эксплуатации старый интерпретатор.

Источники

[1] devguide.python.org — Status of Python versions — https://devguide.python.org/versions/

[2] herodevs.com — Python 3.10 End of Life (October 2026): Security and Migration Guide — https://www.herodevs.com/blog-posts/python-3-10-end-of-life-october-2026-security-and-migration-guide

[3] discuss.python.org — Python 3.10 EOL: Is there an official end-of-support date within October 2026? — https://discuss.python.org/t/python-3-10-eol-is-there-an-official-end-of-support-date-within-october-2026/108064

[4] docs.retool.com — Python 3.10 end of life — https://docs.retool.com/changelog/python-3-10-end-of-life

[5] peps.python.org — PEP 632 – Deprecate distutils module — https://peps.python.org/pep-0632/

[6] docs.python.org — distutils — Building and installing Python modules — https://docs.python.org/library/distutils.html

[7] peps.python.org — PEP 594 – Removing dead batteries from the standard library — https://peps.python.org/pep-0594/

[8] discuss.python.org — PEP 594 has been implemented: Python 3.13 removes 20 stdlib modules — https://discuss.python.org/t/pep-594-has-been-implemented-python-3-13-removes-20-stdlib-modules/27124

[9] peps.python.org — PEP 686 – Make UTF-8 mode default — https://peps.python.org/pep-0686/

[10] github.com — pypa/pip-audit — https://github.com/pypa/pip-audit

[11] alexwlchan.net — Auditing my local Python packages — https://alexwlchan.net/2026/python-package-audit/

[12] docs.astralinux.ru — Python — Документация для разработчиков — Astra Linux — https://docs.astralinux.ru/latest/start/python/

[13] wiki.astralinux.ru — Astra Linux Common Edition 2.12.43: установка Python версии 3.7 — https://wiki.astralinux.ru/pages/viewpage.action?pageId=147162390

[14] peps.python.org — PEP 513 – A Platform Tag for Portable Linux Built Distributions — https://peps.python.org/pep-0513/

[15] blog.trailofbits.com — ABI compatibility in Python: How hard could it be? — https://blog.trailofbits.com/2022/11/15/python-wheels-abi-abi3audit/

[16] pydevtools.com — Wheel: Python Binary Distribution Format — https://pydevtools.com/handbook/reference/wheel/

Быстрые вопросы и ответы

Когда заканчивается поддержка Python 3.10?

По официальному графику ветка 3.10 находится в режиме исправлений безопасности до октября 2026 года. Перед планированием нужно сверить актуальную дату на python.org.

Где искать забытые Python-скрипты?

На серверах и рабочих станциях, в cron и планировщиках, контейнерах, CI/CD, ETL, папках интеграций и репозиториях, а также в процессах, которые запускаются вручную.

Почему нельзя просто заменить интерпретатор?

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

Как доказать, что обновлённый скрипт работает так же?

Старую и новую версии запускают на одном контрольном наборе данных, сравнивают результат, побочные эффекты, время работы и обработку ошибок.

Что должно быть в плане отката?

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

Нужна помощь по этой задаче?
На странице услуги «Инвентаризация зависимостей и безопасный план обновлений» указаны состав работ, результат и фиксированная цена.