Skip to content

필사 모드: Python Ecosystem 2026 Deep-Dive — Python 3.13 · FastAPI · Django 5 · Litestar · SQLAlchemy 2 · Polars · Pydantic 2 · Ruff · uv · mypy

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

> "By 2026, Python is no longer the 'slow language.' Pydantic is in Rust, Polars is in Rust, Ruff and uv are in Rust — every hot path of Python has moved into a systems language." — PyCon US 2026 keynote

Python lived through its biggest toolchain swap in 2025–2026. pip became uv (Astral, Rust-based). Black + isort + flake8 + pylint collapsed into a single Ruff binary. pandas gave way to PyArrow-backed pandas or, increasingly, to Polars. Four foundational tools changed at once — something Python has never seen in 30 years of history. And the engine behind all of them is Rust.

The language itself shifted too. Python 3.13 (2024-10) shipped an experimental JIT (PEP 744) and a free-threaded build (PEP 703). Python 3.14 (2025-10) stabilized both and refined the per-interpreter GIL. As of May 2026 Python is becoming "a language with types, native async, and the option to drop the GIL for multithreaded throughput." This post tours the language, web frameworks, ORM/data, validation, toolchain, testing, concurrency, ML adjacencies, CLIs, scraping, and real adoption stories in Korea and Japan.

1. The Python ecosystem in 2026 at a glance

The 2026 Python ecosystem can be summarized as five layers.

| Layer | 2020 standard | 2026 standard | Note |

|---|---|---|---|

| Package manager | pip + virtualenv | uv | 10–100x faster |

| Linter/formatter | Black + isort + flake8 + pylint | Ruff | Single binary |

| Type checker | mypy | mypy or pyright | Two strong options |

| Validation | pydantic 1 (pure Python) | Pydantic 2 (Rust core) | 5–50x faster |

| DataFrame | pandas 1.x | Polars or pandas 2 (Arrow) | New code goes Polars |

| Web API | Flask, Django REST | FastAPI, Litestar, Django 5 async | ASGI normalized |

| Async | asyncio | asyncio + anyio | Structured concurrency |

The takeaway: **Python is converging on a single toolchain, but the internals of those tools are diverging into Rust**. Your code is still Python; the code that processes your code is no longer.

2. Python 3.13 — JIT preview, free-threaded, better error messages

Python 3.13 (2024-10) introduced three changes that affect both backend and data work.

First, the **experimental JIT compiler (PEP 744)**. A copy-and-patch JIT compiles hot loops into native code. As of 2026 a 5–15% improvement is typical; gains are limited where the workload is dominated by C extension calls such as NumPy. Second, the **free-threaded build (PEP 703)**, shipped as `python3.13t` / `python3.14t`, completely removes the GIL. CPU-bound multithreaded code finally scales linearly with core count. Third, **improved error messages** — `NameError` suggests similar names, indentation errors render visually.

Install free-threaded Python 3.13 with uv

uv python install 3.13t

uv venv --python 3.13t

source .venv/bin/activate

Check GIL status

python -c "import sys; print('GIL enabled:', sys._is_gil_enabled())"

False in a free-threaded build

Enable the JIT and confirm

PYTHON_JIT=1 python -c "import sys; print('JIT:', sys._jit.is_enabled())"

Few teams run free-threaded in production yet — Granian and some data-processing workloads are early adopters. C extension compatibility is the dominant blocker.

3. Python 3.14 — Stabilized JIT and per-interpreter GIL

Python 3.14 (2025-10) is the polishing release for 3.13's experiments. The JIT is still "experimental" but regressions have shrunk, and the free-threaded build was promoted to a stable PEP. **Per-interpreter GIL (PEP 684)** lets a single process host multiple subinterpreters with their own GIL each, opening a path for WSGI/ASGI servers to exploit multiple cores without the cost of forking.

New syntax notably includes the stabilization of **PEP 695 (generic syntax)** and the arrival of **PEP 750 (t-strings, template string literals)**. T-strings let you enforce auto-escaping in security-sensitive contexts like SQL or shell construction. PEP 695 generics let you write `def first[T](items: list[T]) -> T:` style declarations directly on classes and functions, and t-strings use `t"SELECT * FROM users WHERE name = ..."` syntax so the runtime can keep the values separate from the template.

4. uv — replacing pip and Poetry at once

Astral's **uv** has, since its 2024 debut, aggressively consumed the Python package-manager market through 2025–2026. It is a single Rust binary that subsumes pip / pip-tools / virtualenv / pyenv / pipx / Poetry / PDM. Benchmarks put it at 10–100x faster than pip + venv, and its cache-backed lockfiles deliver reproducible installs.

pyproject.toml (uv standard)

[project]

name = "myapi"

version = "0.1.0"

requires-python = ">=3.13"

dependencies = [

"fastapi[standard]>=0.115",

"sqlalchemy[asyncio]>=2.0",

"pydantic>=2.9",

"uvicorn[standard]>=0.30",

"httpx>=0.27",

]

[dependency-groups]

dev = [

"pytest>=8.3",

"pytest-asyncio>=0.24",

"ruff>=0.7",

"mypy>=1.13",

]

[tool.uv]

managed = true

default-groups = ["dev"]

The commands are intuitive: `uv init`, `uv add fastapi`, `uv sync`, `uv run pytest`, `uv pip install -r requirements.txt`. Existing Poetry projects migrate via `uv migrate`, and because uv follows the PEP 621 `pyproject.toml` standard, migration risk is low. As of May 2026, more than 70% of the top 100 PyPI packages ship uv-compatible metadata.

5. Ruff — one tool to replace four

Ruff is Astral's Rust-based linter and formatter. It unifies more than 700 rules from Black + isort + flake8 + pylint into one binary, and runs on average 10–100x faster. As of 2026 nearly every major OSS project — FastAPI, Pydantic, Polars, Hugging Face, pandas — has migrated to Ruff.

Add to pyproject.toml

[tool.ruff]

line-length = 100

target-version = "py313"

[tool.ruff.lint]

select = [

"E", # pycodestyle errors

"W", # pycodestyle warnings

"F", # pyflakes

"I", # isort

"B", # flake8-bugbear

"C4", # flake8-comprehensions

"UP", # pyupgrade

"N", # pep8-naming

"S", # bandit (security)

"RUF", # ruff-specific

]

ignore = ["E501"] # line length is handled by the formatter

[tool.ruff.format]

quote-style = "double"

indent-style = "space"

`ruff check . --fix && ruff format .` finishes a full cleanup in a single line. Even on huge monorepos, a full check completes in under a second, which makes the pre-commit overhead essentially disappear.

6. mypy versus pyright — the type-checker duopoly

The type-checker space is dominated by **mypy (written in Python, originally from Dropbox)** and **pyright (written in TypeScript, by Microsoft)**. mypy 1.13 (2025) supports PEP 695 generics, PEP 696 type defaults, and PEP 692 TypedDict for kwargs; pyright is the engine behind VS Code Pylance and offers the fastest incremental inference.

pyproject.toml — mypy and pyright side by side

[tool.mypy]

python_version = "3.13"

strict = true

warn_return_any = true

warn_unused_configs = true

disallow_untyped_defs = true

plugins = ["pydantic.mypy", "sqlalchemy.ext.mypy.plugin"]

[[tool.mypy.overrides]]

module = "third_party_without_stubs.*"

ignore_missing_imports = true

[tool.pyright]

include = ["src"]

exclude = ["**/__pycache__"]

pythonVersion = "3.13"

typeCheckingMode = "strict"

reportMissingImports = "error"

reportMissingTypeStubs = "warning"

The choice is clear. Pick mypy when you need **CI/CD-grade type assurance** (longer history, PEP authority). Pick pyright when you need **VS Code integration and fast incremental analysis**. More teams are running both — mypy in CI, pyright in the editor.

7. FastAPI 0.115+ — automatic OpenAPI · DI · Pydantic 2

FastAPI (2018–, Sebastián Ramírez) is still the de-facto standard for Python APIs in 2026. 80K+ GitHub stars, 200M+ monthly PyPI downloads. 0.115 bumps to Starlette 0.41 and Pydantic 2.9, pushing validation throughput even higher. Its core value is three-fold: automatic OpenAPI generation, type-driven dependency injection, and Pydantic 2 validation integration.

Idiomatic FastAPI + Pydantic 2 + SQLAlchemy 2 async pattern

from fastapi import FastAPI, Depends, HTTPException

from pydantic import BaseModel, EmailStr, Field

from sqlalchemy.ext.asyncio import AsyncSession

from typing import Annotated

app = FastAPI(title="User API", version="1.0")

class UserCreate(BaseModel):

email: EmailStr

name: str = Field(min_length=1, max_length=50)

age: int = Field(ge=0, le=150)

class UserOut(BaseModel):

id: int

email: EmailStr

name: str

async def get_db() -> AsyncSession:

async with AsyncSessionLocal() as session:

yield session

DbSession = Annotated[AsyncSession, Depends(get_db)]

@app.post("/users", response_model=UserOut, status_code=201)

async def create_user(payload: UserCreate, db: DbSession) -> UserOut:

user = User(**payload.model_dump())

db.add(user)

await db.commit()

await db.refresh(user)

return UserOut.model_validate(user, from_attributes=True)

The `Annotated[Type, Depends(...)]` pattern is recommended from 0.95 onward; 0.115 added small wins like sub-dependency caching options.

8. Django 5.1+ — async views finally mature

As of May 2026 Django 5.2 LTS is the current stable, and **async views have finally reached real-world maturity**. Django 5.1 stabilized async ORM methods (`aget`, `acreate`, `afilter`); 5.2 added async signals, async aggregation, and async middleware. The shift from WSGI + Gunicorn to ASGI + uvicorn/Daphne is now underway in earnest.

Django 5 async view — real concurrent processing

from django.http import JsonResponse

from django.views.decorators.http import require_GET

from asgiref.sync import sync_to_async

@require_GET

async def aggregate(request):

async with httpx.AsyncClient() as client:

Fetch two upstream APIs concurrently

a, b = await asyncio.gather(

client.get("https://api1.example.com/data"),

client.get("https://api2.example.com/data"),

)

async ORM

user = await User.objects.aget(pk=request.user.id)

return JsonResponse({

"user": user.email,

"data1": a.json(),

"data2": b.json(),

})

Django's strength remains its integrated package — Admin, Auth, Migrations, ORM all in one. Larger SaaS shops favor a hybrid where business logic lives in Django and the API gateway is FastAPI/Litestar.

9. Litestar 2.x — the controller-based next-gen ASGI

Litestar (formerly Starlite, 2021–) is the controller-based ASGI framework usually picked by teams unhappy with FastAPI's function-based API. 2.x adds DTO (Data Transfer Object) support, msgspec integration, first-class OpenTelemetry, and Channels (WebSocket pub/sub) — enterprise-shaped features.

Litestar 2.x — controller-based

from litestar import Controller, Litestar, get, post

from msgspec import Struct

class User(Struct):

id: int

name: str

class UserController(Controller):

path = "/users"

@get("/")

async def list_users(self) -> list[User]:

return [User(id=1, name="Alice")]

@post("/")

async def create_user(self, data: User) -> User:

return data

app = Litestar(route_handlers=[UserController])

Litestar recommends msgspec as the default validation engine. msgspec is 2–5x faster than Pydantic 2 at serialization/deserialization with lower memory use. But Pydantic 2 still dominates IDE integration and ecosystem reach, so msgspec alone is rarely a decisive enough reason to leave FastAPI.

10. Flask 3.x · Sanic · Quart · aiohttp 4 · Robyn — the rest of the field

Flask 3 (2023) survives as the classic WSGI microframework. Async views are supported but limited; the body of Flask is still synchronous. **Quart** is a near-identical-API fork that sits on ASGI — the async camp for Flask fans. **Sanic** bundles its own ASGI server in a single async package. **aiohttp 4** is the classic async HTTP library covering both client and server.

**Robyn** is a newer attempt: Rust core with a Python interface. The router, middleware, and HTTP parser are all in Rust, invoking Python handlers. Simple routing benchmarks show 2–3x the throughput of uvicorn + FastAPI. Adoption is cautious because the ecosystem is narrow and Python-debugger integration is rough.

| Framework | ASGI/WSGI | Validation engine | 2026 recommended use |

|---|---|---|---|

| FastAPI 0.115+ | ASGI | Pydantic 2 | Default choice |

| Litestar 2.x | ASGI | msgspec | Controller / enterprise |

| Django 5.2 | WSGI/ASGI | DRF · Ninja | Full-stack |

| Flask 3 | WSGI | None | Existing codebases |

| Quart | ASGI | None | Async for Flask fans |

| Sanic | ASGI | dataclasses | Single-package async |

| Robyn | ASGI (Rust) | Pydantic 2 | Extreme routing speed |

| aiohttp 4 | ASGI | None | Dual client/server |

11. Starlette — common ancestor of FastAPI and Litestar

Starlette is the microframework that layers routing, middleware, and a test client on top of the ASGI standard. FastAPI takes Starlette as a direct dependency; Litestar has its own implementation but a very similar interface. Used standalone, `from starlette.applications import Starlette` is the one-line starting point — you compose routes and middleware by hand, which is also the best way to understand what FastAPI and Litestar are adding on top.

12. Granian — the Rust ASGI server taking on uvicorn

**Granian** is a Rust-based ASGI/WSGI/RSGI server from the author of the Emmett framework. It delivers 1.5–2x more throughput than uvicorn (uvloop + httptools) and naturally exploits multithreaded workers on free-threaded Python 3.13t.

Install with `uv add granian` and run via `granian --interface asgi main:app` as a uvicorn drop-in replacement. Tune workers and threads simultaneously with `--workers 4 --threads 2`. Granian's own RSGI mode (lighter than ASGI) activates with `--interface rsgi`.

As of May 2026, Granian sits as a "uvicorn-compatible drop-in," and both FastAPI and Litestar mention it alongside uvicorn in their docs. uvicorn is still the default, but performance-sensitive deployments are gradually moving over.

13. Pydantic 2 — Rust-core validation engine

Pydantic 2 (2023) is a validation engine rewritten with a Rust core. It runs 5–50x faster than v1, and JSON serialization approaches orjson speed. Nearly every API library on Python — FastAPI, Django Ninja, Litestar, LangChain, the OpenAI SDK — runs on top of Pydantic 2.

from pydantic import BaseModel, Field, EmailStr, computed_field, model_validator

from datetime import datetime

from typing import Self

class Order(BaseModel):

id: int

email: EmailStr

items: list[str] = Field(min_length=1)

quantity: int = Field(gt=0)

price_per_item: float = Field(gt=0)

created_at: datetime

@computed_field

@property

def total(self) -> float:

return self.quantity * self.price_per_item

@model_validator(mode="after")

def check_premium_quota(self) -> Self:

if self.quantity > 1000 and "@example.com" not in self.email:

raise ValueError("non-premium accounts limited to 1000")

return self

Serialization

order = Order(id=1, email="a@b.com", items=["sku-1"], quantity=10, price_per_item=99.0,

created_at=datetime.now())

print(order.model_dump_json())

Pydantic 2's central trick is `pydantic-core`, which moves every validation step into Rust. The Python side is a thin wrapper.

14. msgspec · attrs · dataclasses · cattrs — validation alternatives

Pydantic 2 is not the only choice. **msgspec** is a faster serialization library that Litestar adopts by default. **attrs** is the class-definition library that influenced the stdlib. **dataclasses** is the stdlib's own answer, and **cattrs** layers structuring/unstructuring on top of attrs/dataclasses.

| Tool | Validation | Serialization speed | Learning curve | Ecosystem |

|---|---|---|---|---|

| Pydantic 2 | Strong | Fast | Moderate | Massive |

| msgspec | Moderate | Very fast | Low | Medium |

| attrs | Weak | Fast | Low | Large |

| dataclasses | None | Fast | Very low | stdlib |

| cattrs | Strong | Fast | Moderate | Medium |

| marshmallow | Strong | Moderate | High | Legacy |

15. SQLAlchemy 2.x — unified Core + ORM async

SQLAlchemy 2.0 (2023) unified the Core and ORM APIs. The signature changes are `select()`-based unified queries, `AsyncSession`, type-hint-first mapping, and PEP 695 generic compatibility. As of May 2026 the latest is 2.0.36, and the asyncio dialects officially support PostgreSQL (asyncpg), MySQL (aiomysql), SQLite (aiosqlite), and MSSQL (aioodbc).

SQLAlchemy 2 — async + typed mapping

from sqlalchemy import select, String

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

from datetime import datetime

class Base(DeclarativeBase):

pass

class User(Base):

__tablename__ = "users"

id: Mapped[int] = mapped_column(primary_key=True)

email: Mapped[str] = mapped_column(String(255), unique=True)

name: Mapped[str] = mapped_column(String(50))

created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)

engine = create_async_engine("postgresql+asyncpg://user:pw@localhost/db", echo=True)

AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False)

async def find_recent_users(session: AsyncSession) -> list[User]:

stmt = select(User).where(User.created_at > datetime(2026, 1, 1)).order_by(User.id)

result = await session.scalars(stmt)

return list(result)

The `Mapped[...]` type annotation is the source of truth for column metadata, and integration with mypy/pyright is clean.

16. SQLModel · Tortoise · Peewee · Piccolo · Edgy — ORM choices

| ORM | Foundation | Async | Migrations | Recommended use |

|---|---|---|---|---|

| SQLAlchemy 2 | Independent | Yes | Alembic | Large-system standard |

| SQLModel | SQLAlchemy + Pydantic | Yes | Alembic | FastAPI default |

| Django ORM | Django | Yes (5.1+) | Built-in | Full-stack |

| Tortoise ORM | Independent | Yes | aerich | Django-style ASGI |

| Peewee | Independent | Partial | External | Small projects |

| Piccolo | Independent | Yes | Built-in | Async-first |

| Edgy | SQLAlchemy core | Yes | Built-in | Newcomer |

| Beanie | MongoDB + Pydantic | Yes | None | NoSQL async |

SQLModel layers Pydantic validation onto SQLAlchemy 2's column mapping, delivering the "one model = ORM + API DTO" pattern. With FastAPI's docs co-recommending it, that pattern has become the de-facto standard.

17. Polars — pandas successor candidate

**Polars** (Rust + Apache Arrow) rapidly took share from pandas through 2024–2025. It is a multithreaded query engine with lazy evaluation and the Arrow memory model. On large data (>1GB) it runs 5–30x faster than pandas, and data teams at NAVER (Korea) and ZOZO (Japan) have publicly stated that all new ETL is written in Polars.

eager API

df = pl.read_csv("orders.csv")

result = (

df.filter(pl.col("country") == "KR")

.group_by("user_id")

.agg([

pl.col("amount").sum().alias("total"),

pl.col("order_id").count().alias("orders"),

])

.sort("total", descending=True)

.head(10)

)

lazy API — query planner optimization

plan = (

pl.scan_parquet("logs/*.parquet")

.filter(pl.col("status") == 200)

.group_by("path")

.agg(pl.col("latency_ms").mean())

)

print(plan.explain()) # inspect the execution plan

top_paths = plan.collect()

The biggest hurdle for pandas migrants is Polars' lack of an index concept. Polars treats every column equally, so pandas' `.set_index()` / `MultiIndex` patterns have to be re-modeled.

18. pandas 2.x · PyArrow · DuckDB — coexistence inside the data stack

pandas 2.x (2023–) made PyArrow a first-class backend and improved memory use and string-dtype performance. From 2.2 onward `pd.options.future.infer_string = True` is the norm and copy-on-write is default. Even teams not migrating to Polars can pick up large performance gains by switching pandas 2 to the PyArrow backend.

**DuckDB** is an in-process OLAP database that runs SQL directly against pandas/Polars DataFrames. It has become the fastest analytics tool in Jupyter, and its `httpfs` extension lets you query S3/HTTP files directly.

Run SQL directly against a Polars DataFrame

df = pl.read_csv("orders.csv")

result = duckdb.sql("""

SELECT user_id, COUNT(*) AS orders, SUM(amount) AS total

FROM df

WHERE country = 'KR'

GROUP BY user_id

ORDER BY total DESC

LIMIT 10

""").pl() # back to Polars

Query S3 Parquet directly

duckdb.sql("INSTALL httpfs; LOAD httpfs;")

top = duckdb.sql("""

SELECT path, AVG(latency_ms) AS avg_lat

FROM read_parquet('s3://bucket/logs/*.parquet')

WHERE status = 200

GROUP BY path

""").df()

19. pytest · pytest-asyncio · hypothesis · polyfactory — the testing standard

pytest is the single testing standard for Python. As of May 2026 pytest 8.3 and pytest-asyncio 0.24 are recommended. **hypothesis** is a property-based testing tool that explores input space automatically to find edge cases. **polyfactory** auto-generates fake data from Pydantic/dataclass/SQLAlchemy models.

pytest + hypothesis

from hypothesis import given, strategies as st

@given(st.lists(st.integers(min_value=0, max_value=1000), min_size=1))

def test_sum_is_nonneg(xs: list[int]) -> None:

assert sum(xs) >= 0

pytest-asyncio

@pytest.mark.asyncio

async def test_user_create(client):

response = await client.post("/users", json={

"email": "a@b.com", "name": "Alice", "age": 30

})

assert response.status_code == 201

polyfactory

from polyfactory.factories.pydantic_factory import ModelFactory

class UserFactory(ModelFactory[UserCreate]):

__model__ = UserCreate

def test_random_users():

for _ in range(100):

u = UserFactory.build()

assert u.age >= 0

Parallel execution is pytest-xdist, coverage is coverage + pytest-cov, mutation testing is mutmut.

20. asyncio · anyio · trio — async concurrency

Python's concurrency story is built around stdlib **asyncio**. Its cancellation semantics and task-group model are tricky, which is why **anyio** emerged as an abstraction layer. anyio supports both asyncio and trio backends, and delivers a structured concurrency model. **trio** itself, by Nathaniel Smith, is a separate async library with strong academic/design coherence but a narrower ecosystem.

anyio — structured concurrency

async def fetch(url: str) -> int:

async with httpx.AsyncClient() as client:

r = await client.get(url)

return r.status_code

async def main():

async with anyio.create_task_group() as tg:

for url in ["https://a.example", "https://b.example", "https://c.example"]:

tg.start_soon(fetch, url)

When the task group exits, all children are guaranteed cleaned up

anyio.run(main)

FastAPI 0.110+ / Starlette 0.36+ adopted anyio internally, and as of May 2026 new async code is recommended to follow anyio's patterns.

21. NumPy 2 · SciPy · scikit-learn · transformers · PyTorch — ML adjacencies

NumPy 2.0 (2024) brought ABI changes, a new string dtype, and a simplified API. SciPy 1.13+ is NumPy 2-compatible, and scikit-learn 1.5+ added NumPy 2 plus experimental free-threaded support. PyTorch 2.5+ stabilized `torch.compile` and began experimental free-threaded support. transformers 4.45+ and JAX 0.4+ both integrate parts of Pydantic 2 validation.

In ML workloads the data pipeline has consolidated on **Polars + DuckDB + PyArrow**, training on **PyTorch + Lightning + datasets**.

22. Typer · Click · argparse · fire — CLI camps

There are four CLI choices. **Typer** (FastAPI's sister project, type/Pydantic-based), **Click** (Flask side, decorator-based), **argparse** (stdlib), and **fire** (Google, exposes objects automatically). With Typer the function's type hints are the CLI options — write `def ingest(path: Path, workers: int = 4, dry_run: bool = False) -> None:` and add `@app.command()` to get a complete CLI.

uv + Typer is the cleanest way to combine "CLI script + automatic install": `uv tool install mycli` registers the binary on your system PATH.

23. httpx · playwright-python · Scrapy 2.12 — HTTP clients and scraping

**httpx** (Encode) is the async successor to requests. It keeps the requests API while adding async, HTTP/2, SOCKS, and OAuth, and `async with httpx.AsyncClient(http2=True) as client:` handles HTTP/2, connection pooling, and timeouts in a single line. **playwright-python** is the browser-automation standard, displacing Puppeteer/Selenium. **Scrapy 2.12** is the heavyweight crawling framework; lightweight parsing uses **parsel** (split out of Scrapy).

24. Korean adoption — Toss · Naver · Coupang · Kakao

**Toss** put Python at the heart of its ML platform and data pipelines. Model serving runs on FastAPI + Pydantic 2 + Granian; feature engineering runs on Polars + DuckDB. A Q3 2025 engineering post documented "Polars yielding 8x faster ETL than pandas."

**Naver** uses Python for search-ranking feature engineering and Clova model serving, and in late 2025 announced it would standardize on Polars-first for internal data. **Coupang** serves ads/search ML on FastAPI + Pydantic 2 + SQLAlchemy 2, with Ruff + uv standardized across its monorepo. **Kakao** serves KoGPT-family inference on FastAPI + PyTorch + ONNX Runtime.

25. Japanese adoption — Mercari · ZOZO · LINE · SmartNews

**Mercari** wrote its entire ML-2 platform (introduced in 2024) on FastAPI + Pydantic 2 and partially adopted msgspec on the serialization hot path. **ZOZO** finished migrating its fashion-recommendation feature pipeline from pandas to Polars during 2025 and standardized internal linting on Ruff.

**LINE** uses FastAPI + SQLAlchemy 2 async for both its ad system and its recommendation system, and presented its Granian rollout at PyCon JP 2025 in Tokyo. **SmartNews** built its content-ranking training pipeline on PyTorch + Polars + DuckDB.

26. Toolchain migration — recommended 2026 setup

If you bootstrap a Python project to the 2026 standard, the safest combo is below. Don't migrate everything at once on existing projects — go gradually.

2026 recommended pyproject.toml setup

[project]

name = "myproject"

requires-python = ">=3.13"

dependencies = [

"fastapi[standard]>=0.115",

"pydantic>=2.9",

"sqlalchemy[asyncio]>=2.0",

"polars>=1.12",

"httpx>=0.27",

]

[dependency-groups]

dev = [

"pytest>=8.3",

"pytest-asyncio>=0.24",

"hypothesis>=6.115",

"ruff>=0.7",

"mypy>=1.13",

"pyright>=1.1.385",

]

[tool.ruff]

line-length = 100

target-version = "py313"

[tool.ruff.lint]

select = ["E", "W", "F", "I", "B", "C4", "UP", "N", "S", "RUF"]

[tool.mypy]

python_version = "3.13"

strict = true

plugins = ["pydantic.mypy", "sqlalchemy.ext.mypy.plugin"]

[tool.pytest.ini_options]

asyncio_mode = "auto"

addopts = "--strict-markers -ra"

Migration order: **(1) Poetry/pip to uv**, **(2) Black + isort + flake8 to Ruff**, **(3) pandas to Polars (new code only)**, **(4) pydantic 1 to pydantic 2 (careful — it is a breaking change)**. Don't pick between mypy and pyright; the most stable pattern is mypy in CI plus pyright in the IDE.

27. Conclusion — Python's hot path moved to Rust

If you compress 2026 Python into one sentence: "**the language stayed, the tools went to Rust**." Your code is still Python, but every essential tool that processes it — package manager (uv), linter/formatter (Ruff), validation engine (Pydantic 2 / pydantic-core), DataFrame (Polars), ASGI server (Granian) — is written in Rust.

The language itself is evolving via Python 3.13's free-threaded build and JIT, and 3.14's per-interpreter GIL and t-strings. By around 2030 a GIL-less Python is likely to be the default. Until then, the playbook is to learn the **Pydantic 2 + SQLAlchemy 2 + Polars + FastAPI/Django/Litestar + Ruff + uv** stack, apply it to new projects, and migrate older ones gradually.

References

- Python official docs: https://docs.python.org/3/

- FastAPI: https://fastapi.tiangolo.com/

- Django: https://docs.djangoproject.com/en/5.2/

- Litestar: https://litestar.dev/

- Starlette: https://www.starlette.io/

- SQLAlchemy: https://docs.sqlalchemy.org/en/20/

- Polars: https://pola.rs/

- Pydantic: https://docs.pydantic.dev/latest/

- Ruff: https://docs.astral.sh/ruff/

- uv: https://docs.astral.sh/uv/

- mypy: https://mypy.readthedocs.io/

- pyright: https://github.com/microsoft/pyright

- pytest: https://docs.pytest.org/

- DuckDB: https://github.com/duckdb/duckdb

- msgspec: https://jcristharif.com/msgspec/

- Granian: https://github.com/emmett-framework/granian

현재 단락 (1/356)

Python lived through its biggest toolchain swap in 2025–2026. pip became uv (Astral, Rust-based). Bl...

작성 글자: 0원문 글자: 23,937작성 단락: 0/356