5分钟构建API接口服务 | python小知识
1. 什么是API
我们经常会使用一些API接口来完成特定的功能,比如查询天气的数据,下载股票的数据,亦或是调用ChatGPT模型的结构等等。
API全称是Application Programming Interface,即应用程序接口,它通常提供了一个功能函数,而这个功能函数的输入和输出是和调用方相互约定的。
从架构上来讲,API通常从客户端和服务端模型;客户端以数据形式向服务器发送请求,服务器使用该客户端输入来开始执行内部函数,并将输出数据返回到客户端。
所以我们要开发一个API接口,从设计上就需要明确:
- 你要提供什么样的功能
- 功能的输入是什么
- 功能的输出返回是什么
从技术上,要提供一个服务来接收请求和返回结果,通常是一个满足HTTP协议的HTTP接口,也可以是RPC接口。我们这里要讲的是HTTP接口
这也是API的本质。
2. 用Flask构建API
要实现一个API,我们要构建一个HTTP服务。HTTP(超文本传输协议)是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范,是一个典型的请求/响应模式的协议。
Flask是python中轻量的web框架,Flask的两个核心模块除了模板渲染之外就是请求响应处理,其中请求响应处理是由 Werkzeug(WSGI 工具库)完成,而模板渲染是由Jinja(模板渲染库)完成。
Flask因为轻量灵活,用来构建API接口十分合适。
2.1 Flask入门
安装Flask
pip install flask
我们看一个简单的例子:
from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def hello():
return 'hello world'
if __name__ == '__main__':
app.run("0.0.0.0", debug=True, port=6006)
调用(假设上面的文件为hello.py):
python hello.py
此时,你调用http://127.0.0.1:6006/hello
就会返回hello world
。
上面是最简单的一个接口了,从上面我们可知Flask的工作机制:
Flask(__name__)
申明了一个服务appapp.run
来启动这个服务,包括服务的地址ip和端口@app.route
装饰器定义了接口访问的URL地址和方法(GET/POST)hello
的函数就是具体接收请求响应的函数功能模块,由@app.route
装饰
2.2 实用的FlaskAPI
上面的例子显然是不能满足一个完整的API的功能,首先我们要接收请求的数据,Flask是通过request
来接收请求数据,HTTP请求通常由两个方式GET和POST。
from flask import Flask
from flask import request
import json
import traceback
app = Flask(__name__)
@app.route('/hello')
def hello():
return 'hello world'
@app.route('/v1/task', methods=['GET', 'POST'])
def do_task():
try:
print(request.method)
if request.method == "GET":
content = request.args.get("content")
# comment = request.values.get("content")
res = int(content) + 10
print(res, type(content))
elif request.method == "POST":
print("========", request.headers)
content_type = request.headers.get('Content-Type')
if "multipart/form-data" in content_type:
form_data = dict(request.form)
# files_data = dict(request.files)
# print(form_data)
res = int(form_data.get('content')) + 14
elif "application/json" in content_type:
# request.get_data() # 原始的数据
input_dict = request.get_json()
res = input_dict.get('content') + 12
elif "application/x-www-form-urlencoded" in content_type:
input_dict = request.form
# request.values.get("content")
else:
print(request.get_data())
print('url: %s , script_root: %s , path: %s , base_url: %s , url_root : %s' % (
request.url, request.script_root, request.path, request.base_url, request.url_root))
return json.dumps({"code": 0, "msg":"success", "data": res})
except:
err_msg = 'url: %s, err_msg: %s' % (request.url, (str(traceback.format_exc())))
print(err_msg)
return json.dumps({"code": -1, "msg":"failed", "data": 0})
if __name__ == '__main__':
app.run("0.0.0.0", debug=True, port=6006)
以GET方式请求
http://127.0.0.1:6006/v1/task?content=3
# {"code": 0, "msg": "success", "data": 13}
# 127.0.0.1 - - [20/Mar/2023 23:53:28] "GET /v1/task?content=3 HTTP/1.1" 200 -
以POST方式请求
POST是通过表单form的方式来传递数据,数据可以使用不同的Content-Type来发送。比如:
- application/json 的方式 ,请求body体的内容就是{"a": "b", "c": "d"}
- application/x-www-form-urlencoded 的方式,则body体的内容就是 a=b&c=d
- multipart/form-data 通常是要上传文件
POST请求调用如下:
import requests
import json
url = 'http://127.0.0.1:6006/v1/task'
headers = {'content-type': "application/json", 'Authorization': 'APP appid = 4abf1a,token = 9480295ab2e2eddb8'}
s = json.dumps({'content': 1, 'key2': 'value2'})
r = requests.post(url, data=s, headers=headers)
print(r.text)
url = 'http://127.0.0.1:6006/v1/task'
files = {'file': open('lena.jpg', 'rb')}
s = {'content': 1, 'key2': 'value2'}
r = requests.post(url, files=files, data=s)
print(r.text)
除此之外,从上面的例子可知:
- GET方式是通过
request.args
获取数据 - POST方式是通过
request.get_json()
request.get_data()
request.form
获取数据 request.method
获取请求方式request.headers
获取HTTP头信息
3. 总结
今天分享了用Flask构建API接口,总结如下:
- API的本质是客户端访问服务端的函数,访问的方式是一个HTTP请求(HTTP接口)
- HTTP请求有GET和POST
- Flask用request接收客户端请求
- POST请求有不同的类型,json或者x-www-form-urlencoded或者multipart/form-data,不同的方式有不同的接收方式
- API接口返回通常以json形式返回