• HOME
  • /
  • ARTICLES
  • /
  • 軽量かつ非同期で実装できるおすすめのフレームワーク、Starlette👍
python / Starlette
Created at:2/21/2020 Updated at:3/2/2020

軽量かつ非同期で実装できるおすすめのフレームワーク、Starlette👍

標準的なWebシステムを作る場合はDjangoがおすすめですが、軽量で非同期なAPIを作りたいこともよくあります。そんな場合に最近よくつかっているのがStarletteというasgiに対応したフレームワークです。

Starletteの特徴

encode/starlette
The little ASGI framework that shines. 🌟. Contribute to encode/starlette development by creating an account on GitHub.
async/awaitでコントローラーを実装できる
バックグラウンドタスクの実装が簡単でわかりやすい
データベースをちょっと触りたいときもショートコードで書けるように同じ作者のライブラリが準備されている
ウェブソケット対応
uvicornで複数のワーカーを起動できる

開発はDjango Restframeworkを作っているEncodeという会社でTomChristieさんの会社です。彼はすばらしい設計、実装をされる方で、私はよく彼のコードを読んで、自分の書き方を直したりすることがあったりするほど、お手本としている方です。
他にもPythonの有名なライブラリをたくさん開発している@kennethreitzさんがResponderの下地に使っていたり、速くて、マイクロサービス向きなAPIベースのフレームワークです。以下のコードはWebsocketの実装ですが、見たとおりスッキリとしています。


# Pipfile

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[scripts]
dev = "uvicorn main:app --host 127.0.0.1 --debug --port 5000"

[dev-packages]
autopep8 = "*"
flake8 = "*"
ipython = "*"

[packages]
starlette = "*"
starlette-prometheus = "*"

[requires]
python_version = "3.7"


# main.py

import os
import uuid
import logging
import datetime
from os.path import dirname, basename

import uvicorn
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
from starlette.applications import Starlette
from starlette import status
from starlette.types import Receive, Scope, Send
from starlette.websockets import WebSocket
from starlette.endpoints import WebSocketEndpoint
from starlette.responses import PlainTextResponse
from starlette_prometheus import metrics, PrometheusMiddleware


logger = logging.getLogger(__name__)

DEBUG = os.environ.get('DEBUG')
app = Starlette()

# NOTE: You can use prometheus.
app.add_middleware(ProxyHeadersMiddleware)
app.add_middleware(PrometheusMiddleware)
app.add_route("/metrics", metrics)


@app.exception_handler(status.HTTP_403_FORBIDDEN)
@app.exception_handler(status.HTTP_404_NOT_FOUND)
@app.exception_handler(status.HTTP_500_INTERNAL_SERVER_ERROR)
async def server_error(request, exc) -> str:
    return PlainTextResponse(f"{exc.status_code} ERROR")


@app.on_event('startup')
async def init_server() -> None:
    pass
    # DO SOMETHING


@app.websocket_route("/")
class App(WebSocketEndpoint):


    async def on_connect(self, socket: WebSocket) -> None:
        token = socket.query_params.get('token')
        if token:
            await socket.accept()
        else:
            await socket.close()

    async def on_disconnect(self, socket: WebSocket, close_code: int) -> None:
        pass

    async def on_receive(self, socket: WebSocket, data: dict) -> None:
        if not data['code']:
            await self.send_message(socket, {
                'status': 'error',
                'result': 'empty code.'
            })
        else:
            await self.send_message(socket, data)

    async def send_message(self, socket: WebSocket, data: dict) -> None:
        await socket.send_json(data)


if __name__ == "__main__":
    uvicorn.run(
        app,
        port=5000,
        proxy_headers=True,
        workers=2
    )

私は主に解析、非同期で実行したいタスク、スクレイピングなどを別のアプリケーションからエンドポイント経由で実行したい時によく使っています。
ここ最近ではKerasでNNを実行して、モデルを作らせるAPIとして実装しました。

パフォーマンス

starlette.png

PythonのWeb系のフレームワークのうち、Uvicornに次ぐ最高のパフォーマンスを発揮します。実際、StarletteはUvicornを使用して実行していますし、開発者も同じ方です。
Djangoも3.0でasgiへ転換を行っていますし、RX系が流行りだしてから非同期でアプリを作るのがスタンダードなってきています。また、ミドルウェアでCORS, ホストのアクセス制御,Prometheusエクスポーターがあります。こうしてみると、Kubernetesでの利用に向いていて、私はほとんどのインフラ設計をKubernetesで実装しているため、扱いやすく、利用頻度が高いので、お気に入りなんだと思います。

ググると記事もちらほらあるので、意外と人気?

Starlette’s API made this emulator as quick to produce as I could possibly hope for. The framework is still new, but I think it has a very promising future in the Python ecosystem. It already has the best performance of any Python framework in the TechEmpower Benchmarks. I hope you enjoyed looking at some async programming in Python.

Quote source: https://www.mattlayman.com/blog/2019/starlette-mock-service/

StarletteでAPIアプリを実装して、GCPにCloudRunでデプロイしてみる

以下の手順で実装からGCPへのデプロイまですぐにできるので、迅速な開発が行えます。
ただ、最初から開発する機能が多く見込まれている場合はDjango+Restframeworkにしておいたほうが、開発スピードが早いです。どちらも同じ作者なのでフルスタック、軽量どちらのAPIも選択肢を用意されている感じでしょうか。
Gitのリポジトリを作っておきましたので、以下のトピックを複数回に渡って紹介したいと思います。

Gitでリポジトリをクローンする
docker-composeで依存しているミドルウェアを起動する
python main.pyでStarletteを起動する
APIのエンドポイントを追加する
バックグラウンドタスクを追加する
pytestで非同期処理をテストする
CI/CDはCloudBuildで利用して、継続的にテスト、CloudRunへデプロイできるようにする
CloudRunが起動しているのを確認したら削除する
ksh3/starlette-cloudrun
Starlette framework on GCP CloudRun. Contribute to ksh3/starlette-cloudrun development by creating an account on GitHub.

Related Articles

python / Starlette
Created at:2/28/2020 Updated at:3/2/2020
速くて軽量なAPI、Starletteを使ってGCPにデプロイする Part1
前に紹介したPythonの軽量APIフレームワークStarletteのGCP(CloudRun)で、開発からリリースまで対応したGitリポジトリを作成しているので、トピックごとに詳細と開発の仕方について紹介しています。

Policy

Reproduction or reproduction of all or part of this article is prohibited without the consent of the copyright holder. However, citations are only accepted if the author and article URLs are displayed.