HN 日本語サマリー

← 一覧へ戻る
Web開発

Pyronaut の紹介

Introducing Pyronaut (pyronaut.io)

8 pointsby grashalm0 コメント

要約

Pyronaut は、GraalVM と Micronaut を基盤とした、本番環境対応サービス構築のための高性能 Python アプリケーションプラットフォームです。Python の AST を Java コンパイラと統合し、GraalVM と Graal JIT による実行時最適化により、高いパフォーマンスとスケーラビリティを持つ Python サービスを実現します。これにより、Python で開発されたサービスは、従来の FastAPI や Flask よりも大幅に高いスループットと低いレイテンシを実現し、JVM エコシステムの成熟したフレームワークを活用できるようになります。また、Micronaut Data によるビルド時 SQL クエリ生成や、Java ライブラリとのシームレスな連携も可能です。

全文翻訳

← Blog Pyronaut の紹介 2026年10月2日 Graeme Rocher 発表 本日、GraalVM と Micronaut を基盤とした、本番環境対応サービス構築のための高性能 Python アプリケーションプラットフォームである Pyronaut の提供開始を発表できることを嬉しく思います。 Pyronaut とは? Pyronaut は、Python AST を Java コンパイラと融合させ、GraalVM と Graal JIT による実行時最適化により、非常に高性能でスケーラブルな Python サービスを可能にすることで、Micronaut と GraalVM (AOT コンパイル、ビルド時検証、ソースコード処理など) の同じアイデアとメリットを Python にもたらします。AI の成長のおかげで、Python は今日、世界で最も人気のある言語の 1 つであり、今日から Python は、JVM エコシステムで最も成熟し、スケーラブルで人気のあるフレームワークの 1 つ上で使用できるようになります。サーバーサイド言語として Python を選択することは、もはやスループットの低下とレイテンシの増加を意味しません。 最小の Pyronaut アプリケーション main.py を作成: from micronaut.http.annotation import Get @Get("/") def read_root() -> dict: return {"Hello": "World"} @Get("/items/{item_id}") def read_item(item_id: int, q: str | None = None) -> dict: return {"item_id": item_id, "q": q} 実行: pyronaut dev main.py デプロイ: pyronaut run main.py スケーラビリティ Netty によるパワーアップ Micronaut は、あらゆる言語で世界で最もスケーラブルで高性能な非同期フレームワークの 1 つである Netty を基盤としています。Pyronaut では、Python コードは同じ Netty ベースの HTTP サーバーによって提供され、Graal JIT によって最適化されます。当社のベンチマークでは、これは FastAPI の 2.6 倍のスループットと Flask の 6.5 倍のスループットを、より低いレイテンシで実現することを意味します (この投稿の後半で詳しく説明します)。 Python の asyncio パイプラインを Netty イベントループに直接接続したため、非同期/await をネイティブに使用して、スケーラブルなノンブロッキングサービスを記述できます。 import asyncio from micronaut.http.annotation import Get @Get("/slow-hello") async def slow_hello() -> str: await asyncio.sleep(0.5) # コルーチンを中断しますが、イベントループは中断しません return "hello" asyncio.run() も uvicorn もありません。Pyronaut が関数を呼び出すときにはすでにイベントループが存在しており、asyncio.gather や asyncio.TaskGroup は期待どおりに機能します。 これをストリーミングに拡張したため、SSE、websockets、その他のユースケースのストリーミングサービスを記述するために async を使用できます。yield を含む任意の async def ルートは、バックプレッシャーでクライアントにストリーミングバックされます。 from dataclasses import dataclass from typing import AsyncIterator from java.time import Duration from micronaut.http import MediaType from micronaut.http.annotation import Get from micronaut.sse import Event from micronaut_asyncio import as_async_iterable from reactor.core.publisher import Flux @Serdeable @dataclass class Tick: index: int label: str @Get(value="/ticks", produces=MediaType.TEXT_EVENT_STREAM) async def ticks() -> AsyncIterator[Event[Tick]]: every_second = Flux.interval(Duration.ofSeconds(1)).take(3) async with as_async_iterable(every_second) as seconds: async for second in seconds: yield Event.of(Tick(second, f"tick-{second}")) Java ライブラリ (Reactor など) がネイティブ Python async/await で「そのまま動作する」ように、任意のリアクティブ Publisher または Java CompletableFuture を await で活用できます。たとえば、組み込みの Micronaut HttpClient を使用して、async/await でノンブロッキング REST 呼び出しを行うことができます。 from dataclasses import dataclass from typing import Annotated from jakarta.inject import Inject from micronaut.http import HttpRequest from micronaut.http.annotation import Get from micronaut.http.client import HttpClient from micronaut.http.client.annotation import Client from micronaut.serde.annotation import Serdeable @Serdeable @dataclass class Repo: name: str stargazers_count: int github: Annotated[HttpClient, Inject, Client("https://api.github.com")] @Get("/repos/{owner}/{name}") async def repo(owner: str, name: str) -> Repo: request = HttpRequest.GET(f"/repos/{owner}/{name}").header("User-Agent", "pyronaut") return await github.retrieve(request, Repo) データアクセス Micronaut Data ほとんどの Python Web フレームワークでは、データアクセスは開発者に任されています。ORM を選択し、セッションを配線し、クエリが実際に機能するかどうかを実行時に確認します。Pyronaut には Micronaut Data が含まれており、Python でリポジトリを定義でき、お気に入りのデータベース用の SQL クエリをビルド時に事前計算します。実行時のクエリ変換はなく、存在しないプロパティを参照するクエリは、本番環境でのリクエストではなくビルド時に失敗します。 from dataclasses import dataclass from typing import Annotated from jakarta.inject import Inject from jakarta.transaction import Transactional from micronaut.data.annotation import GeneratedValue, Id, MappedEntity, Query from micronaut.data.jdbc.annotation import JdbcRepository from micronaut.data.model import Page, Pageable from micronaut.data.repository import CrudRepository from micronaut.http.annotation import Body, Get, Post from micronaut.serde.annotation import Serdeable @Serdeable @MappedEntity @dataclass class Rocket: id: Annotated[int | None, Id, GeneratedValue] name: str thrust: float @JdbcRepository(dialect="ORACLE") class RocketRepository(CrudRepository[Rocket, int]): def findByNameContains(self, fragment: str) -> list[Rocket]: ... def findTop3ByThrustGreaterThanOrderByThrustDesc(self, thrust: float) -> list[Rocket]: ... def findNameByThrustLessThan(self, thrust: float) -> list[str]: ... def findAll(self, pageable: Pageable) -> Page[Rocket]: ... @Query("SELECT * FROM rocket WHERE LOWER(name) LIKE LOWER(:pattern)") def search(self, pattern: str) -> list[Rocket]: ... def update(self, id: Annotated[int, Id], thrust: float) -> None: ... rockets: Annotated[RocketRepository, Inject] @Post("/rockets") @Transactional def launch(fleet: Annotated[list[Rocket], Body]) -> list[Rocket]: return [rockets.save(rocket) for rocket in fleet] @Get("/rockets/strongest/{thrust}") def strongest(thrust: float) -> list[Rocket]: return rockets.findTop3ByThrustGreaterThanOrderByThrustDesc(thrust) @Get("/rockets/page/{number}") def page(number: int) -> Page[Rocket]: return rockets.findAll(Pageable.from_(number, 2)) 派生ファインダー、プロジェクション、ページネーション、明示的なクエリ、部分更新、トランザクションはすべて標準で提供されます。 $ curl http://localhost:8080/rockets/strongest/5000 [{"id":5,"name":"Starship","thrust":74000.0},{"id":1,"name":"Saturn V","thrust":35100.0},{"id":3,"name":"Ariane 6","thrust":10400.0}] 同じプログラミングモデルは、JDBC、R2DBC、Hibernate/JPA、Hibernate Reactive、MongoDB、Azure Cosmos DB で動作するため、Python 開発者は長年 Micronaut ユーザーが信頼してきたのと同じ成熟したデータアクセス層を利用できます。 Python と javac の結婚 Pyronaut は Python のソースコードプロセッサであり、Python ソースを分析し、Java アノテーションを見るたびに Python デコレータを自動的に表面化します。このアプローチにより、ビルド時検証や先行コンパイルを含む、成熟した Micronaut フレームワークコア全体を Python 言語にもたらすことができました。実際には、Micronaut のすべての部分が Python で「そのまま動作」し、Python 開発者はプラットフォーム全体に完全にアクセスできます。 Micronaut Serialization を使用してシリアライズ可能なデータクラスを記述できます。これは、高速で効率的な JSON シリアライズ/デシリアライズを提供するビルド時シリアライザ/デシリアライザを計算します。 from dataclasses import dataclass from typing import Annotated from com.fasterxml.jackson.annotation import JsonProperty from micronaut.serde.annotation import Serdeable @Serdeable @dataclass class Book: title: str quantity: Annotated[int, JsonProperty("qty")] Micronaut ルート (Python で定義) からビルド時に OpenAPI 仕様を生成できます。ドキュメンテーション文字列は API を説明するために使用されます。 from io.swagger.v3.oas.annotations import OpenAPIDefinition from io.swagger.v3.oas.annotations.info import Info from micronaut.http.annotation import Get OpenAPIDefinition(info=Info(title="Greeting