Python
Python — мова загального призначення, чий стандартний інтерпретатор виконує код Python в одному потоці за раз, а важкі обчислення лишає скомпільованим бібліотекам. Саме через це блокування, GIL, чотири потоки рідко бувають учетверо швидшими, вебсервери на Python працюють кількома процесами, а повільний сервіс потребує діагнозу до лікування: він чекає чи обчислює? Сторінка починається з дванадцяти навантажень і інструмента, що справді пришвидшує кожне; далі — GIL і нова збірка без нього, asyncio, версії й щорічний реліз, типи й пакування, вебсервери та їхня пам’ять, п’ять задокументованих кейсів і те, де все це вироджується.
- Поточна версія
- 3.14 · 3.15 — 1 жовт. 2026
- Модель
- Python виконує один потік за раз
- Підтримка
- 5 років: 2 — виправлення, 3 — безпека
Чекає чи обчислює? Дванадцять навантажень і те, що допомагає
Кожне питання продуктивності в Python починається з того самого діагнозу. Програма повільна тому, що чекає, — на мережу, диск, базу даних, — чи тому, що обчислює? На графіку латентності ці два випадки виглядають однаково. У Python вони лікуються протилежно, бо стандартний інтерпретатор дає виконувати код Python лише одному потоку за раз. Робота, що чекає, добре розходиться по потоках; обчислення, написані на Python, не розходяться зовсім. Ось дванадцять поширених навантажень, діагноз для кожного і те, що справді допомагає. Наступні розділи посилаються на рядки за номерами.
| # | Навантаження | Чекає чи обчислює | Чи допоможуть потоки? | Що справді допомагає |
|---|---|---|---|---|
| 1 | 500 викликів зовнішнього API | Чекає | Так | asyncio з асинхронним клієнтом або пул потоків |
| 2 | В’юха Django, що чекає на базу даних | Чекає | Так — але скільки, вирішує вебсервер | Більше воркерів сервера або потоки в кожному (gthread) |
| 3 | Завантаження чи читання 10 000 файлів | Чекає | Так | ThreadPoolExecutor |
| 4 | requests.get() чи time.sleep() усередині async def | Чекає — в єдиному потоці циклу | Ні: це зупиняє кожну іншу корутину | Асинхронний клієнт або asyncio.to_thread() |
| 5 | Цикл на чистому Python по 10 мільйонах рядків | Обчислює, на Python | Ні | Одна операція над масивом у NumPy, pandas чи Polars або пул процесів |
| 6 | Розбір CSV-файлу на 2 ГБ | Обчислює | Не з модулем csv | Читач, написаний на C чи Rust, — pandas, Polars, pyarrow |
| 7 | Множення великих матриць NumPy | Обчислює, на C | Не потрібно — бібліотека вже займає всі ядра | Нічого; обмежте потоки бібліотеки, коли запускаєте ще й кілька процесів |
| 8 | Зміна розміру зображень у Pillow | Обчислює, на C | Часто — багато операцій звільняють блокування | Потоки, а для великих пакетів — процеси |
| 9 | Інференс моделі в PyTorch | Обчислює, на C++ чи на GPU | Бібліотека сама звільняє блокування | Групуйте запити; один процес на GPU |
| 10 | Робота на чистому Python, що має зайняти всі ядра в одному процесі | Обчислює, на Python | Лише на збірці без GIL | python3.14t, якщо кожне розширення це підтримує; інакше процеси |
| 11 | Утиліта командного рядка, що стартує дві секунди | Імпорт модулів | Ні | python -X importtime, потім ліниві імпорти (3.15) |
| 12 | API, де перетворення об’єктів на відповідь забирає більшість часу | Обчислює, на Python | Ні | Скомпільований серіалізатор — orjson або Pydantic 2, чиє ядро написано на Rust |
GIL і збірка без нього
CPython, стандартний інтерпретатор, захищає свої нутрощі одним блокуванням — глобальним блокуванням інтерпретатора, GIL. Потік має тримати його, щоб виконувати байт-код Python. Потоки справжні, потоки операційної системи, і плануються звичайно, але Python виконує лише той, хто тримає блокування. Типово кожні 5 мілісекунд власника просять його відпустити, щоб інші отримали свою чергу; який потік піде наступним, обирає операційна система. Запустіть три потоки рахувати числа на машині з трьома вільними ядрами — і отримаєте пропускну здатність одного ядра плюс ціну перемикань.
Друга половина правила й лишає потоки корисними. Потік, що чекає — на сокет, файл, відповідь бази даних, — на час очікування звільняє блокування, і так само роблять добре написані C-розширення під час довгої роботи: NumPy, pandas, PyTorch, драйвери баз даних. Це рядки 1–3 і 7–9. Саме блокування існує через те, як CPython керує пам’яттю. Кожен об’єкт має лічильник посилань, що змінюється щоразу, коли щось починає чи перестає його використовувати. Два потоки, що водночас змінюють той самий лічильник, зіпсують його, а одне велике блокування робило кожен лічильник безпечним майже без витрат для програми з одним потоком.
Збірка без GIL
Прибрати блокування — означає зробити кожен лічильник посилань і кожен вбудований тип безпечним інакше. PEP 703 описав як, і впроваджують це поетапно. Python 3.13, у жовтні 2024 року, вийшов з окремою експериментальною збіркою без GIL. Python 3.14, у жовтні 2025-го, зробив цю збірку офіційно підтримуваною, хоч і досі необов’язковою та окремою: ви ставите python3.14t поруч зі звичайним інтерпретатором. Ціна для однопотокового коду тепер «приблизно 5–10%», за нотатками до релізу, — значно менше, ніж у 3.13. Python 3.15 додає стабільний двійковий інтерфейс для збірок без GIL, тож бібліотека може постачати один скомпільований пакет для кількох версій. Зробити збірку без GIL типовою — окреме рішення, і дати в нього немає.
Підступ — у розширеннях. C-розширення має оголосити, що воно безпечне без блокування. Якщо ви імпортуєте таке, що не оголосило, інтерпретатор без GIL вмикає блокування знову для всього процесу й друкує попередження — тож одна стара залежність тихо повертає вас до стандартної поведінки. Перш ніж переносити рядок 10 на python3.14t, перевірте кожну скомпільовану залежність, а не лише власний код.
| Варіант | Що виконується паралельно | Чого це коштує | Для чого брати |
|---|---|---|---|
| Потоки, стандартна збірка | Очікування і C-код, що звільняє блокування | Небагато; пам’ять спільна | Рядки 1–3 і 7–9 |
| Процеси — пул процесів, кілька воркерів сервера | Усе | Пам’ять цілого інтерпретатора на кожен; дані копіюються між ними | Обчислення на Python сьогодні |
Субінтерпретатори — concurrent.interpreters, 3.14 | Код Python, по блокуванню на інтерпретатор | Жодних спільних об’єктів; багато розширень ще не підтримуються | Ізольовані обчислювальні задачі в межах одного процесу |
Збірка без GIL — python3.14t | Код Python у звичайних потоках | Близько 5–10% на однопотоковому коді; кожне розширення має це підтримувати | Рядок 10, коли залежності готові |
asyncio: один потік і три способи його зупинити
asyncio — відповідь стандартної бібліотеки на рядки 1–3: цикл подій (event loopодин потік, що виконує все по черзіЦикл в одному потоці, що бере з черги готову роботу — відповідь, яка прийшла, таймер, що спрацював, — і виконує її колбек, по одному за раз. Він дає одному потоку тримати тисячі очікувань одночасно й зупиняється для всіх, поки виконується будь-який один колбек.Докладніше в статті →Усі терміни) в одному потоці, що виконує багато корутин по черзі. Корутина — функція, оголошена через async def, — виконується, доки не дійде до await на чомусь неготовому, віддає керування циклу й відновлюється, коли приходить відповідь. Так в одному потоці можуть бути в польоті десять тисяч з’єднань. До нього часто тягнуться як до загального пришвидшення, а це не воно. Він накладає очікування; обчисленням він не допомагає нічим. І він залежить від того, що кожен шматок коду співпрацює, — саме тут він і ламається.
Перший спосіб зупинити його — рядок 4. Блокуючий виклик — requests.get(), time.sleep(), класичний драйвер бази даних — ніколи не повертає керування. Єдиний потік циклу сидить усередині нього, і кожна інша корутина чекає, хоч би якою готовою була її власна відповідь. Одна бібліотека без підтримки async здатна перекреслити весь задум, і це найчастіша причина, чому asyncio-сервіс виявляється повільнішим за багатопотоковий, який він замінив.
| Усередині `async def` це блокує цикл | Натомість |
|---|---|
requests.get() | httpx.AsyncClient або aiohttp |
time.sleep() | await asyncio.sleep() |
psycopg2 та інші класичні драйвери баз даних | psycopg 3 в асинхронному режимі, asyncpg |
| SDK без асинхронної версії | await asyncio.to_thread(call, …) — виклик іде в робочому потоці |
| Читання чи запис великого файлу | Так само asyncio.to_thread() |
| Важкі обчислення (рядки 5, 6, 12) | loop.run_in_executor() з пулом процесів |
Другий спосіб губить роботу без жодної помилки. asyncio.create_task() запускає корутину у фоні, а документація містить попередження, яке більшість ніколи не читає: «Цикл подій тримає на задачі лише слабкі посилання. Задачу, на яку немає посилань деінде, може будь-коли прибрати збирач сміття — навіть до її завершення». Задача «запустив і забув» — надіслати лист, записати аудит — може просто зникнути. Тримайте посилання на кожну задачу або запускайте їх усередині asyncio.TaskGroup (Python 3.11), що чекає на всі й скасовує решту, якщо одна впала.
Третій спосіб — очікування без кінця. Корутина, що чекає на сервіс, який ніколи не відповість, назавжди займає своє місце в циклі, і коли таких набирається досить, сервісу бракує з’єднань чи пам’яті. Обгортайте кожен зовнішній виклик в asyncio.timeout() (теж 3.11) або задавайте клієнту власний тайм-аут.
Версії: одна на рік, п’ять років кожна
Нова версія Python виходить щожовтня. Вона отримує два роки виправлень помилок — 18 місяців для версій до 3.13, — далі лише виправлення безпеки, до п’яти років від релізу, а потім — нічого. Python 2 дійшов до цієї точки 1 січня 2020 року, після того як дату його кінця вже відсунули на п’ять років. Таблиця перелічує, що кожна недавня версія додала такого, що ви зустрінете в коді, і коли закінчуються її виправлення безпеки.
| Версія | Випущено | Що ви зустрінете в коді | Патчі безпеки до |
|---|---|---|---|
| 3.9 | жовт. 2020 | Злиття dict через |, list[int] без імпорту, zoneinfo | Завершено жовт. 2025 |
| 3.10 | жовт. 2021 | Інструкція match, X | None у підказках типів, зрозуміліші повідомлення про помилки | Жовт. 2026 — цього місяця |
| 3.11 | жовт. 2022 | У середньому в 1,25 раза швидший, except*, asyncio.TaskGroup, tomllib | жовт. 2027 |
| 3.12 | жовт. 2023 | Псевдоніми type і синтаксис узагальнень, f-рядки, що можуть повторювати лапки, distutils прибрано | жовт. 2028 |
| 3.13 | жовт. 2024 | Експериментальні збірка без GIL і JIT, нова інтерактивна оболонка, cgi і telnetlib прибрано | жовт. 2029 |
| 3.14 | жовт. 2025 | Підтримувана збірка без GIL, шаблонні рядки t"…", анотації, що обчислюються на вимогу, concurrent.interpreters, Zstandard | жовт. 2030 |
| 3.15 | Заплановано 1 жовт. 2026 | UTF-8 за замовчуванням, явні ліниві імпорти, frozendict, семплювальний профайлер Tachyon | жовт. 2031 |
Типи й пакування: хай перевіряє машина
Python перевіряє типи, коли виконує код, а не коли ви його зберігаєте. Саме це робить його швидким у написанні — і саме це робить велику кодову базу ризикованою: помилка в назві атрибута стає AttributeError у продакшені, а не червоним підкресленням. Відповіддю, на якій мова зупинилася, стали підказки типів: анотації, які інтерпретатор ігнорує, а перевіряч читає, щоб знайти помилку до релізу. mypy — перший перевіряч, Pyright стоїть за більшістю редакторів, а ty від Astral з’явився як бета в грудні 2025 року. Підказки поступові: анотуйте межі модуля сьогодні, його нутрощі наступного місяця — і підвищуйте суворість перевіряча свідомо.
Там, де дані входять у систему, самих підказок замало: підказка каже, що має прийти, а не що прийшло. Pydantic закриває цей розрив, перевіряючи й приводячи реальні дані до анотації під час виконання, — тому він і лежить під FastAPI та більшістю сучасного Python-коду для APIApplication Programming Interface — контракт між програмамиПравила, за якими одна програма звертається до іншої: які запити можна надіслати, у якому вигляді й що прийде у відповідь. Для того, хто звертається, це контракт — усе, що за ним, лишається чорною скринькою, і саме тому другий бік можна переписати, не зламавши вас.Докладніше в статті →Усі терміни. Запускайте статичний перевіряч у збірці, валідуйте на межі — і дайте типам описувати все, що між ними.
Пакування — друга річ, яку треба зробити правильно рано, бо його збої тихі. Кожен проєкт отримує власне віртуальне середовище — сучасні дистрибутиви Linux узагалі відмовляються робити pip install у системний Python, з помилкою «externally-managed-environment». Залежності оголошують у pyproject.toml, а точні розв’язані версії лягають у файл блокування, який комітять. Без нього двоє розробників і сервер збірки працюють із трьома різними наборами залежностей, і різниця виявляється як баґ, якого ніхто не може відтворити. Кожен інструмент мав власний формат такого файлу; з березня 2025 року є стандартний — pylock.toml.
| Задача | Класичні інструменти | Поширене у 2026 |
|---|---|---|
| Встановити, розв’язати й зафіксувати залежності | pip з pip-tools, Poetry | uv, Poetry |
| Віртуальні середовища й версії Python | venv, virtualenv, pyenv | uv |
| Лінтинг і форматування | flake8, isort, Black | Ruff |
| Перевірка типів | mypy | mypy, Pyright, ty (бета) |
uv, Ruff і ty походять від однієї компанії, Astral, і написані на Rust — здебільшого тому вони в десять-сто разів швидші за інструменти, які замінюють. У березні 2026 року Astral оголосила, що погодилася приєднатися до OpenAI, і заявила, що інструменти лишаться відкритими. Це привід спиратися на стандарти — pyproject.toml, pylock.toml, звичайні віртуальні середовища, — а не на приватні можливості одного інструмента, щоб перехід лишався дешевим.
Два індекси, одне ім’я
Компанії часто публікують внутрішні пакети в приватний індекс і додають його через --extra-index-url поруч із публічним — PyPI. Пастка в тому, як обирає pip. Він не віддає переваги вашому індексу. Він «об’єднує версії-кандидати з усіх індексів і обирає найкращу з об’єднаного набору», словами документації uv. Тож якщо хтось опублікує на PyPI пакет із тим самим ім’ям і вищим номером версії, pip поставить саме його — і виконає його код. Це називається dependency confusion. Типова поведінка uv протилежна: використовується лише перший індекс, у якому є це ім’я. Ця поведінка існує через кейс, зображений на схемі.
Django, FastAPI і сервер під ними
Два фреймворки покривають більшість серверного Python, і побудовані вони на протилежних припущеннях, а не є конкурентами різного рівня якості. Django дає повний застосунок — ORMObject-Relational Mapping — обʼєкти замість SQLБібліотека, що підставляє обʼєкти мови там, де в базі лежать рядки таблиці, — тож SQL ви майже не пишете. Зручність коштує контролю: згенерований запит буває значно важчим за той, який ви написали б самі, і зʼясовується це вже під навантаженням.Докладніше в статті →Усі терміни, міграції, автентифікацію, адмінку, форми, шаблони — і очікує, що ви будуватимете всередині нього. FastAPI дає маршрутизацію, валідацію й документацію і очікує, що решту ви оберете самі. Flask досі лишається розумним мінімальним вибором; більшість нової роботи над API йде у FastAPI, бо валідація й згенерована схема OpenAPIмашиночитний опис APIОдин файл, що описує HTTP-API у машиночитному вигляді: маршрути, параметри, формати відповідей. З нього генерують документацію, клієнтські бібліотеки й заглушки для тестів — і саме це не дає опису розійтися з кодом.Докладніше в статті →Усі терміни беруться з тих самих підказок типів, які ви й так писали.
Django
- Усе в комплекті: адмінка, автентифікація, ORM і міграції є вже першого дня.
- Синхронний за природою; асинхронні в’юхи є, а ORM асинхронний лише частково.
- Поточний — 6.1; LTSLong-Term Support — реліз, що роками отримує патчіЛінія релізів, що й далі отримує виправлення безпеки та критичних багів упродовж оголошеного строку після виходу новіших версій, але без нових можливостей. Вона дає команді оновлюватися у власному темпі — до кінцевої дати в таблиці підтримки, після якої наступна вразливість не матиме виправлення взагалі.Усі терміни — 5.2, з патчами до квітня 2028 року.
- Ризик — «товста модель», що росте, доки бізнес-правила можна перевірити лише через в’юхи.
FastAPI
- Асинхронний за задумом, на ASGI — природно пасує сервісам, що здебільшого чекають на інші сервіси.
- Валідація й документація OpenAPI генеруються з ваших підказок типів.
- Досі має версії 0.x, тож читайте нотатки до релізу перед кожним оновленням.
- Ризик — збирати власний стек: ORM, міграції, автентифікацію, адмінку — по одному рішенню за раз.
Модель релізів Django теж змінюється. Сьогодні функціональний реліз виходить кожні вісім місяців, і лише кожен третій — довгостроковий. Наступний такий, 6.2, очікується у квітні 2027 року з підтримкою до квітня 2030-го. З січня 2028 року Django переходить на один реліз на рік із номером за роком — Django 2028, — і кожен реліз отримує ті самі три роки підтримки.
Жоден із фреймворків не запускає себе в продакшені сам. Застосунок Django працює під WSGI-сервером на кшталт Gunicorn; застосунок FastAPI — під ASGI-сервером на кшталт Uvicorn, часто як воркери Gunicorn. Кількість воркерів цього сервера — справжня межа паралельності, і через GIL корисна конфігурація — кілька процесів-воркерів, а не багато потоків в одному. Документація Gunicorn радить починати з «(2 × ядра CPUCentral Processing Unit — процесорПроцесор, що виконує інструкції програми. Коли кажуть, що завдання «впирається в CPU», мають на увазі, що воно обмежене обчисленнями, а не очікуванням диска чи мережі, — і лікуються ці два випадки протилежно, тому розрізняти їх варто одразу.Усі терміни) + 1» і попереджає, що йому «зазвичай потрібно лише 4–12 воркерів». Кількість зазвичай обмежує пам’ять, а не ядра, — і тому варто знати, скільки пам’яті воркери насправді ділять.
Чому воркери ділять менше пам’яті, ніж мали б
Сервер із попереднім форком завантажує застосунок один раз у головному процесі, а потім форкає його у воркери. У Linux дочірній процес після форку спершу ділить із батьківським кожну сторінку пам’яті; сторінку копіюють лише тоді, коли в неї пише одна зі сторін. Це copy-on-write, і завдяки йому двадцять воркерів мали б коштувати трохи більше за одного. Python ламає це двома способами. Читання об’єкта змінює його лічильник посилань — це запис у заголовок об’єкта, — тож саме використання спільних об’єктів копіює сторінки, на яких вони лежать. А прохід збирача сміття торкається кожного відстежуваного об’єкта, тож один прохід може скопіювати більшість спільної пам’яті одразу.
Саме з цієї проблеми вийшли два виправлення. gc.freeze(), доданий у 3.7, переносить кожен об’єкт, що існує на момент виклику, у постійне покоління, яке збирач більше ніколи не відвідує: викличте gc.disable() рано в головному процесі, gc.freeze() — просто перед форком, і gc.enable() — у кожному воркері. А з 3.12 деякі об’єкти безсмертні — None, малі цілі числа, інтерновані рядки, — тож їхні лічильники посилань більше не змінюються. Щоб побачити, чи це важить для вас, порівняйте спільну й приватну пам’ять воркера в /proc/<pid>/smaps_rollup за хвилину після старту й за годину.
П’ять кейсів і те, чого в кожному бракувало
Кожен кейс задокументували ті, з ким він стався: власні записи релізів Python, інженерні блоги, повідомлення проєкту про інцидент, бюлетень безпеки. Разом вони покривають мову, пам’ять, пакування, файли даних і гроші за інтерпретатором.
| Кейс | Що сталося | Чого бракувало |
|---|---|---|
| Python 2 → 3, 2008–2020 | Розрив у тому, як працюють текст і байти, завершувався дванадцять років | Спосіб запускати одну кодову базу на обох версіях із першого дня |
| Instagram, січ. 2017 | Воркери за секунди після старту втрачали третину спільної пам’яті | Збирання сміття, що не чіпає об’єкти батьківського процесу |
| torchtriton, груд. 2022 | Пакет на PyPI з ім’ям приватної залежності крав файли в користувачів нічних збірок | Інсталятор, що тримається індексу, якому належить ім’я |
| Моделі в pickle, 2024–2025 | Близько сотні файлів моделей на Hugging Face виконували код під час завантаження | Формат ваг, що не може виконувати код |
| Faster CPython, 2021–2025 | План пришвидшення вп’ятеро, досягнуто 1,25×, потім фінансування команди припинилося | Фінансування, не прив’язане до одного роботодавця |
Перший кейс — найдовша міграція, якої велика мова вимагала від своїх користувачів. Python 3.0, випущений 3 грудня 2008 року, змінив те, що таке рядок: текст став Unicode, а байти — окремим типом, тож код, що їх змішував, — тобто більшість коду, що торкався файлів чи мережі, — треба було переписати, і він не міг легко працювати на обох версіях. Кінець Python 2.7 призначили на 2015 рік, а потім відсунули на п’ять років; підтримка припинилася 1 січня 2020-го, а останній реліз, 2.7.18, вийшов у квітні 2020 року. Dropbox, чий десктопний клієнт мав понад мільйон рядків Python, почав перехід у 2015 році й закінчив у 2018-му, постачаючи обидва інтерпретатори поруч і поступово перемикаючи користувачів. Того, що зрештою зробило такі переходи можливими, — коду, написаного для обох версій, а потім перевірячів типів, що знаходили зламане, — на старті не існувало. Мова може змінити свої основи раз на покоління і платить за це роками.
Третій кейс — схема з розділу про пакування, лише наживо. Нічні збірки PyTorch залежали від пакета torchtriton, опублікованого у власному індексі PyTorch. До грудня 2022 року пакета з таким ім’ям на PyPI не існувало. Потім хтось його завантажив, і між 25 і 30 грудня 2022 року кожен, хто ставив нічну збірку в Linux через pip, отримував копію з PyPI — «оскільки індекс PyPI має перевагу», як сказано в повідомленні PyTorch. Імпорт запускав бінарник, що зчитував ім’я машини, змінні середовища, /etc/passwd, усе в ~/.ssh і першу тисячу файлів у домашній теці й відправляв їх назовні через DNS-запити. PyTorch перейменував залежність на pytorch-triton, зареєстрував це ім’я на PyPI, щоб його не зайняв ніхто інший, і прибрав уражені збірки. Стабільних релізів це не торкнулося.
П’ятий кейс — про те, хто платить за те, щоб інтерпретатор ставав швидшим. У 2020 році Марк Шеннон опублікував план зробити CPython приблизно вп’ятеро швидшим за чотири етапи, кожен приблизно на 50%, і з 2021 року Microsoft фінансувала невелику команду разом із Гвідо ван Россумом, щоб його виконати. Робота була справжньою: 3.11, за нотатками до релізу, став у середньому в 1,25 раза швидшим, а в 3.13 з’явився експериментальний JITJust-In-Time compilation — компіляція під час роботиКомпіляція коду тоді, коли програма вже працює: середовище спершу виконує його як є, дивиться, які ділянки гарячі, і на ходу перетворює саме їх на машинний код. Тому перші секунди після старту повільніші за наступні хвилини.Усі терміни. У травні 2025 року Microsoft припинила підтримку проєкту й звільнила більшість команди — напередодні мовного саміту на PyCon. Уже злиті покращення лишаються в кожному релізі; пізніші етапи плану втратили головних інженерів. Мова, якою користуються мільйони, у такій роботі досі залежить від того, чи тримає одна компанія на ній кількох людей, — а швидкість, на яку ви плануєте, має бути виміряною, а не взятою з дорожньої карти.
Де він вироджується
На Python поблажливо писати й безжально вгадувати. Майже кожна продакшн-проблема на цій сторінці — це пропущений діагноз, коли рядок першої таблиці сприйняли як інший, або перевірка, яку могла зробити машина, але її не попросили:
- Потоки, додані, щоб пришвидшити обчислення на Python, — блокування гарантує, що це не допоможе (рядки 5 і 10).
- Блокуючий виклик усередині асинхронного обробника зупиняє цикл для всіх інших запитів (рядок 4).
- Фонові задачі без збереженого посилання, що можуть зникнути без жодної помилки.
- Поелементні цикли по масивах там, де один виклик бібліотеки зробив би те саме скомпільованим кодом.
- Спільний між потоками стан, захищений лише вірою в те, що його захищає GIL.
- Підказки типів, написані й ніколи не перевірені, гірші за їх відсутність, бо їм вірять.
- Залежності без файлу блокування або приватний індекс, доданий поруч із PyPI через
--extra-index-url. pickle.loadчиtorch.loadна файлі, створеному кимось іншим.- Кількість воркерів, задана за звичкою, а не за виміряною пам’яттю, і тихо втрачений copy-on-write.
- Версія за межею останньої колонки таблиці версій — з листопада 2026 року все старше за 3.11.
Чесна межа — швидкість інтерпретатора на коді, написаному на самому Python. Для роботи, чий гарячий цикл не можна віддати бібліотеці, — власна симуляція, парсер, алгоритм на кожен запит, — Python у десятки разів повільніший за компільовану мову, і ні потоки, ні asyncio цього не змінюють. Збірка без GIL дає такому коду більше ядер, а не швидкість на кожному. Python виграє там, де повільна частина — очікування, або де хтось уже написав гарячий цикл на C, C++ чи Rust; для решти чесна відповідь — виміряти й перенести гарячий цикл, а не весь сервіс.
Практична перевірка займає п’ять хвилин. Запустіть python --version у продакшн-образі й знайдіть рядок у таблиці версій. Пошукайте закомічений файл блокування і --extra-index-url у збірці. Запустіть тести один раз із PYTHONASYNCIODEBUG=1 і прочитайте, що він залогує. І звірте кількість воркерів сервера з пам’яттю, яку кожен воркер справді використовує, а не з кількістю ядер.
Коли це застосовувати
Застосовуйте, коли
- Робота з даними, аналітика й машинне навчання, де в екосистеми немає серйозного конкурента.
- API та внутрішні сервіси, чий час іде на очікування, — FastAPI з async пасує цій формі точно.
- Продукти, яким швидко потрібні адмінка, акаунти й модель даних, — саме цим і є Django.
- Автоматизація, скриптинг і склеювання систем, де читабельність важить більше за пропускну здатність.
Уникайте, коли
- Обчислення на чистому Python, що мають зайняти всі ядра одного процесу, — якщо не підходять збірка без GIL і всі її розширення.
- Критичні за затримкою шляхи в мікросекундах, де накладні витрати інтерпретатора — головна ціна.
- Великі кодові бази без перевірки типів у збірці, де відсутність компілятора відчувається щорелізу.
- Завантаження файлів моделей чи даних із ненадійних джерел у форматі, що може виконувати код.
Джерела й метод
На чому стоїть ця стаття
- 23 джерела
- 2 задокументовані збої
- Перевірено 13 жовтня 2026 р.
Практики й походження термінів
очікування чи обчислення: потоки, GIL, asyncio, процеси й версії- Документаціяsys — System-specific parameters and functions (setswitchinterval) (відкривається в новій вкладці)docs.python.org
- ДокументаціяPython support for free threading (відкривається в новій вкладці)docs.python.org
- ДокументаціяCoroutines and tasks (відкривається в новій вкладці)docs.python.org
- Документаціяgc — Garbage Collector interface (відкривається в новій вкладці)docs.python.org
- Документаціяpickle — Python object serialization (відкривається в новій вкладці)docs.python.org
- ДокументаціяWhat’s New In Python 3.11 (відкривається в новій вкладці)docs.python.org
- ДокументаціяWhat’s new in Python 3.14 (відкривається в новій вкладці)docs.python.org
- ДокументаціяWhat’s new in Python 3.15 (відкривається в новій вкладці)docs.python.org
- ДокументаціяStatus of Python versions (відкривається в новій вкладці)Python Developer’s Guide
- СтандартPEP 703 – Making the Global Interpreter Lock Optional in CPython (відкривається в новій вкладці)Python Software Foundation
- СтандартPEP 683 – Immortal Objects, Using a Fixed Refcount (відкривається в новій вкладці)Python Software Foundation
- Документаціяuv — Package indexes (відкривається в новій вкладці)Astral
- ДокументаціяGunicorn — Design (відкривається в новій вкладці)gunicorn.org
- ДокументаціяDownload Django — supported versions (відкривається в новій вкладці)djangoproject.com
Збої, на яких вчиться стаття
torchtriton і моделі в pickle у «П’ять кейсів»- ПостмортемCompromised PyTorch-nightly dependency chain between December 25th and December 30th, 2022 (відкривається в новій вкладці)PyTorch · 31.12.2022
- ДослідженняData Scientists Targeted by Malicious Hugging Face ML Models with Silent Backdoor (відкривається в новій вкладці)JFrog · 02.2024
- ДокументаціяPyTorch 2.6.0 Release (відкривається в новій вкладці)GitHub · pytorch/pytorch · 29.01.2025
- Документаціяtorch.load with weights_only=True RCE (CVE-2025-32434) (відкривається в новій вкладці)GitHub Security Advisory · pytorch/pytorch · 18.04.2025
Python 3, Instagram і Faster CPython
три інші кейси- СтандартPEP 373 – Python 2.7 Release Schedule (відкривається в новій вкладці)Python Software Foundation
- СтаттяMax Bélanger, Damien DeVille — How we rolled out one of the largest Python 3 migrations ever (відкривається в новій вкладці)Dropbox · 25.09.2018
- СтаттяChenyang Wu, Min Ni — Dismissing Python Garbage Collection at Instagram (відкривається в новій вкладці)Instagram Engineering · 17.01.2017
- ДокументаціяMark Shannon — faster-cpython: plan (відкривається в новій вкладці)GitHub
- СтаттяMicrosoft’s latest layoffs hit software engineers hard (відкривається в новій вкладці)The Register · 16.05.2025
Дослідження з Claude. Пошук і звірку першоджерел зроблено з Claude (Anthropic). Відбір, текст і перевірку фактів — редакція Anatomy of IT Product.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.