スクリプトのお勉強 技術

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アプリケーションのプロトタイプを作ってみようと思います。

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

執筆者:

関連記事

(小ネタ) python3 date_range + step付き

ちょっと前に同じような感じのネタを。。 したような気がするのだが、まぉおいておこう。。 素のPython3で、日付にてfor文を回す方法 日付で分割して処理をしたいと思うときがあります。例えば、202 …

WSL2にOpenCV + Pythonをインストールする

お手軽にやろうと思ってやってみました。作業手順自体を見ると、お手軽ではないかもしれません。 環境 インストールする/した環境は以下の通りです。 WSL2Ubuntu 20.04.2 LTSPython …

Dockerを使用してGo言語の開発環境を構築する

なんとなくGolangのブロジェクトに機能追加しようと思いました。 Golangの開発用に、Dockerfile等を準備する手順を書いておこうと思います。 サンプルにnfpm サンプルとして、Fork …

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

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

Python Django REST Framework(REST API)の作成

1.はじめに 今回は、pythonの「Django」というWebアプリケーションフレームワークを使用し、REST APIを作成します。作成するREST APIは、これから作るであろう、Nuxt.jsか …

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