スクリプトのお勉強 技術

FastAPIでAPIを作ってみる(その1)

投稿日:2020年7月28日 更新日:

勉強として、FastAPIを使用して、実際にAPIを作成し、起動しようと思います。目標としては、本番運用用の設定まで行いたいと思います。

FastAPIとは

FastAPIとは、Pythonによる、Webアプリケーションフレームワークです。以下の特徴があるそうです。

  • 高速
  • コーディング高速化
  • バグの少なさ
  • 直感的
  • 簡単
  • 重複のなさ
  • 堅牢
  • 標準準拠

特に、標準準拠的に、OpenAPIによるドキュメントを自動生成してくれるのが良い感じに見えました。

どんなAPIを作るの?

あるキーワードAを入力したら、もともと持っているキーワードBと組み合わせて、googleで検索できるURL(クエリURL)を返すAPIを作ろうと思います。

例えば、”食べる” というAPIの入力があるとします。
このAPIの内部ではキーワードとして”ラーメン”(=R)を持っていたとします。

その場合、例えば、このAPIのURL「/queryURL/R?q=食べる」にアクセスすると、APIはgoogle検索に”ラーメン 食べる”としたときのURLを返却します。

具体的には以下になります。

{
  queryURL: 'https://www.google.com/search?q=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3&oq=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3'
}

環境

環境は以下を使用します。

  • Python: 3.6.9
  • pipenv: 2020.06
  • FastAPI: 0.59.0
  • nginx: 1.18.0
  • gunicorn: 20.0.4
  • systemd

構成は以下のようになります。

nginx -> (127.0.0.1:28168) ->
                            gunicorn -> FastAPI(pipenv) -> app.py
                            (systemd)

開発環境設定

最初は、以下で環境を設定しました。

$ pipenv install fastapi[all] uvicorn gunicorn sqlalchemy

sqlalchemy は今は使用しませんが、後で使用する予定です。
あと、Python3のバージョンによっては、dataclassesを入れる必要があるかもしれません。

ソース

ソースは以下に置いておきました。

https://github.com/KenichiTanino/query_url_web_api.git

テスト用起動方法

テスト用にAPIを起動するには以下にします。api:appの”api”はモジュールを指します。つまりapp/api.pyになっていたら”app.api”にします。”:app”は属性を指します。属性というのは、実際のところ、FastAPIを指す変数名です。

$ pipenv run uvicorn api:app --reload --host 0.0.0.0

Swagger UI

目玉のOpenAPIによるドキュメントです。

以下にアクセスすると、

http://192.168.132.128:8000/docs

以下のように表示します。以下を自動生成してくれるのはなかなか便利だと思いました。

FastAPIが自動生成したSwagger UI

設定方法

リポジトリのファイルから、本番まで設定する想定で、設定方法を書いていきます。

手順としては以下の流れになります。

  • インストール(git cloneでファイル配置)
  • systemd登録/起動(gunicorn起動)
  • nginx登録

インストール

リポジトリを/usr/local/queryurlにcloneしたとします。

以下のようにインストールします。

### ユーザ作成(www-data:www-data)
$ sudo useradd -U -M -s /sbin/nologin www-data
$ cd /usr/local
$ sudo git clone https://github.com/KenichiTanino/query_url_web_api.git queryurl
$ cd queryurl
$ export PIPENV_VENV_IN_PROJECT=true
$ /usr/local/bin/pipenv sync
$ mkdir log
$ sudo chown -R www-data:www-data /usr/local/queryurl

systemd(gunicorn)

gunicornを起動するsystemdユニットファイルは以下の通りです。

[Unit]
Description = queryURL service ( gunicorn - fastapi )
Requires=queryurl.socket
After = network-online.target
ConditionPathExists = /usr/local/queryurl

[Service]
User=www-data
Group=www-data
WorkingDirectory = /usr/local/queryurl
ExecStart = /usr/local/bin/pipenv run gunicorn --config /usr/local/queryurl/gunicorn.py api:app
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID
PrivateTmp = true

[Install]
WantedBy = multi-user.target

難しい所はありませんが、ExecStartは/usr/local/bin/pipenvを前提としています。環境に合わせて変更してください。

etc/gnucorn.pyは以下にしています。

import multiprocessing
import os

name = "gunicorn"

accesslog = "/usr/local/queryurl/log/log_access.txt"
errorlog = "/usr/local/queryurl/log/log_error.txt"

bind = "127.0.0.1:28168"

worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 1024
backlog = 2048
max_requests = 5120
timeout = 360
keepalive = 2

debug = os.environ.get("DEBUG", "false") == "true"
reload = debug
preload_app = False
daemon = False

systemd 登録/起動

以下でunitファイルを有効化し、永続的に起動できるようにします。

$ sudo systemctl enable /usr/local/queryurl/etc/queryurl.service
$ sudo systemctl daemon-reload
$ sudo systemctl start queryurl.service

nginx登録

nginx.conf(部分)は以下のようにします。

location /query_url {
    proxy_pass http://127.0.0.1:28168;
    proxy_set_header Host               $host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP          $remote_addr;
}

動作確認

動作しているかどうかは、以下で確認します。

$ curl -G "https://www.tech-law-pyscho.info/query_url/query/G" --data-urlencode "q=テスト"
{"queryURL":"https://www.google.com/search?q=%E8%A1%8C%E6%94%BF%E6%9B%B8%E5%A3%AB+%E3%83%86%E3%82%B9%E3%83%88"}

おわりに

ここではまずnginxに登録してアクセスできるところまで設定しました。

次は、このAPIを使用して、Webアプリケーションのプロトタイプを作ってみようと思います。

-スクリプトのお勉強, 技術

執筆者:

関連記事

seaborn + Pandas + Python によるグラフ描画(その1: 準備編)

グラフ描画してみよう 今現在の仕事で、グラフ描画する可能性があるので、少し練習してみようと思います。 題材について 突然ですが、私は確定拠出型年金に加入しています。証券会社はSBI証券 にしています。 …

no image

GLP-1 メディカルダイエット 58日目

メディカルダイエットして58日目の記録をしておこうと思います。 9回目。 今回は左腹(中部)に打ちました。痛いのはいまだに慣れない。。 土曜にゲットしてした 渋谷に行ってきたが、そこの医院には相変わら …

悪いほうが良い? でも限度があるよね。。

自分のその時の状態によって結論が変わる https://tech.nikkeibp.co.jp/atcl/nxt/column/18/00620/040900010/を見て書こうと思いました。 今やっ …

小ネタ – Python3 でIPv4アドレスの第三オクテットを加算する方法

ホント小ネタです。IPv4アドレスの第四オクテットは単に加算すればいいですが、第三オクテットを加算する方法が見つかりませんでした 通常はしないのかもしれませんが、、そして残念ながら、いい方法がありませ …

vscodeのRemote Developmentで「権限がない」と怒られた時

小ネタです。 vscodeのRemote Developmentにてパスワードなしログイン vscodeは時々使うのですが、リモート開発するのにRemote Developmentが便利なので使ってま …

google オプトアウト Click here to opt-out.