[Python] Flask与Fast API速度比较


背景

我将Flask用作自己作为业余爱好创建的服务后端的API。
几天前,当我看着Qiita时,有一篇这样的文章。

我试图接触由python

制成的最新API框架FastAPI

无论如何它似乎都很快,但是我创建它是因为我找不到任何比较速度的信息。

环境

Windows 10

1
Python 3.6.7 :: Anaconda custom (64-bit)

安装

烧瓶

1
2
pip install flask
pip install falsk_sqlalchemy

快速API

1
2
pip install fastapi
pip install uvicorn

制备

DB和简单的API,我将编写代码来访问API。

sqlite db

我想尝试连接到数据库,所以我将使用SQlite进行尝试。
基本上是参考此处创建的
使用python3运行sqlite3。创建和阅读等基础知识。

测试数据库

1
[(1, 'Taro'), (2, 'Hanako'), (3, 'Hiroki')]

达到API

的家伙

两者都通过交换注释输出来支持。
我不明白如何将参数接收为?Hoge = foo就像FastAPI中的常规GET一样,因此我对URL进行了一些更改。
我想创建一个不执行任何操作的API,以及一个通过传递ID来接收用户名(花子)的API。
运行API 100次,并比较平均时间的速度。

call_api.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
import time

###Flask
URL = 'http://127.0.0.1:5000/'
#Fast API
#URL = 'http://127.0.0.1:8000/'

def main():
    t = []
    for i in range(100):
        start = time.time()
        #say_hello
        url = URL + 'hello'
        res = requests.get(url)
        print(res.text)
        #get_user
        url = URL + 'get_user?user_id=2' #flask
        #url = URL + 'get_user/2' #FastAPI
        res = requests.get(url)
        print(res.text)
        elapsed_time = time.time() - start
        t.append(elapsed_time)
    print(sum(t)/len(t))

if __name__=='__main__':
    main()

Flask和FaxApi都使用SQLAlchemy,这消除了编写SQL的需要。

烧瓶

app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from flask import Flask, render_template, request, logging, Response, redirect, flash, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS

app = Flask(__name__)
CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///./TEST.db'
db = SQLAlchemy(app)

class User(db.Model):
    __tablename__ = 'persons'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)

    def __init__(self, username):
        self.username = username

@app.route('/hello', methods=['GET'])
def say_hello():
    print('hello flask')
    return 'hello'

@app.route('/get_user', methods=['GET'])
def get_user():
    user_id = request.args['user_id']
    username = User.query.get(user_id).name
    return username

if __name__ == '__main__':
    app.run()

快速API

我在复制时创建的。

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from fastapi import FastAPI
from sqlalchemy import Boolean, Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.orm import Session, sessionmaker

app = FastAPI()

SQLALCHEMY_DATABASE_URI = 'sqlite:///./TEST.db'
engine = create_engine(
    SQLALCHEMY_DATABASE_URI, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

class CustomBase:
    # Generate __tablename__ automatically
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

Base = declarative_base(cls=CustomBase)
Base.metadata.create_all(bind=engine)

db_session = SessionLocal()

class User(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, unique=True, index=True)

@app.get("/hello")
def say_hello():
    print('hello fastapi')
    return 'hello'

@app.get("/get_user/{user_id}")
def read_item(user_id: int):
    print(user_id)
    username = db_session.query(User).get(user_id).name
    return username

执行结果

第一行是什么都不做的API,第二行是使用SQL的API,第三行是平均执行时间(秒)。

烧瓶

1
2
3
hello
Hanako
0.03350924015045166

快速API

1
2
3
"hello"
"Hanako"
0.04411268472671509

结论结论

Flask快了一点。
我觉得我不能这么公平地编码,而且我没有做太多处理,所以Flask更快!似乎并非如此,但
可以说,FastAPI的触觉并没有太大区别。
我将继续按原样使用Flask。