Open11

[Python] ちゃんとやる ときどき FastAPI

あざらしあざらし

2回目のぺえちょん FastAPI を立てたけど、使い方を忘れていたりしたのでちゃんとメモっておく

あざらしあざらし

hello world まで

① mkdir でフォルダを作る
② フォルダ直下に移動
python -m venv venv を実行する
.\venv\Scripts\activate を実行し、仮想環境を構築
⇒カレントディレクトリの表示の前に (venv) が出てこればOK

⑤ uvicorn および fastapi をインストール
pip install fastapi "uvicorn[standard]"

⑥ main.py を作成し、公式のハロワをコピペ

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}

uvicorn main:app --reload を実行
⑧ ブラウザで開いて表示されればおk

https://fastapi.tiangolo.com/ja/#_3


なんかつまった(恥)理由

仮想環境を構築するとき、下記URLでは.venv\bin\Activate.batになっていた
コピペしたら「そんなものはない!!!!!」って怒られた。????????

https://packaging.python.org/ja/latest/guides/installing-using-pip-and-virtual-environments/

結論はパスが違っていた
bin じゃなくて Scripts の中だった。はずかちい……


venv スクリプトを実行できない

https://blog.amuse-club.jp/ict/1013/

あざらしあざらし

logging

公式のモジュールがあるので、 C# NLog のようにサードパーティー製のロガーは不要みたい

https://docs.python.org/ja/3/howto/logging.html#

https://qiita.com/FukuharaYohei/items/92795107032c8c0bfd19

https://qiita.com/amedama/items/b856b2f30c2f38665701

今のところ、私の logging.json
{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "simple": {
            "format": "%(asctime)s [%(levelname)-8s]: %(message)s -  %(name)s:%(lineno)s (%(funcName)s)"
        }
    },

    "handlers": {
        "consoleHandler": {
            "class": "logging.StreamHandler",
            "level": "WARNING",
            "formatter": "simple"
        },
        "timeRotatingFileHandler": {
            "class": "logging.handlers.TimedRotatingFileHandler",
            "level": "INFO",
            "encoding": "utf-8",
            "formatter": "simple",
            "filename": "C:\\log\\app.log",
            "when": "D",
            "backupCount": 365
        }
    },

    "loggers": {
        "__main__": {
            "level": "DEBUG",
            "handlers": ["consoleHandler", "timeRotatingFileHandler"],
            "propagate": false
        },
        "same_hierarchy": {
            "level": "DEBUG",
            "handlers": ["consoleHandler", "timeRotatingFileHandler"],
            "propagate": false
        },
        "lower.sub": {
            "level": "DEBUG",
            "handlers": ["consoleHandler", "timeRotatingFileHandler"],
            "propagate": false
        }
    },

    "root": {
        "level": "INFO",
        "handlers": ["consoleHandler", "timeRotatingFileHandler"]
    }
}

main.py で下記のように呼び出す

from logging import getLogger, config

# log
path = Path(__file__).resolve().parent
with open(path.joinpath(LOG), 'r') as f:
    log_conf = json.load(f)

config.dictConfig(log_conf)
logger = getLogger(__name__)
あざらしあざらし

環境ごとに config つくっておきたい

https://qiita.com/vidro/items/2ec1eac2baa719fb0b1f

個人的なやりかた

  1. venv 直下に configフォルダを作成
  2. __init__.pyファイルを作成
なかみ
import argparse

# python main.py に下記のようなパラメータをつけて実行することで読み込む環境ファイルを決める
# ただし、パラメータを何もつけない場合はdevelopmentとして扱う
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--production")
parser.add_argument("-d", "--development")
parser.add_argument("-s", "--staging")

args = parser.parse_args()

if args.production:
    from config.production import *
elif args.staging:
    from config.staging import *
else:
    from config.development import *

  1. 各環境ごとのファイル(development.pyなど)を作成
なかみの例(development)
# environment
ENV = 'development'

# uvicorn
HOST = '127.0.0.1'
PORT = 8000

# web
WEB = 'http://localhost:8931'

# logging
LOG = 'C:\\log\\logging.json'

# DB
DB_HOST = 'localhost'
DB_PORT = '3306'
DB_NAME ='test_name'
DB_USER = 'test_user'
DB_PASS = 'test_pass'
  1. コードを実行するときに下記のように指定すれば各環境の変数でよぶことができるよ!
python venv/main.py -d DEVELOPMENT
あざらしあざらし

Pythonでスネークケースをキャメルケースに変換したい

Pythonは基本スネークケース(user_idみたいな、アンダーバーがあるかんじのね)
これを、連携先に合わせてキャメルケースに変換したあと、FastAPIで連携したい

def snake_to_camel(snake_str):
    components = snake_str.split('_')
    return components[0] + ''.join(x.title() for x in components[1:])

data = {"staff_id": 1, "staff_code": "1111", "staff_name": "適当太郎"}
camel_case_data = {snake_to_camel(key): value for key, value in data.items()}

print(camel_case_data)

これによって出力されるものは下記のようになる!!

{"staffId": 1, "staffCode": "1111", "staffName": "適当太郎"}