提示:分两部分:fastapi接口调用,与nuitka快速打包
功能:作为一名算法工程师,训练机器学习模型只是为客户提供解决方案的一部分。 除了生成和清理数据、选择和调整算法之外,还需交付和部署结果,以便在生产中使用
实现python或基于虚拟环境的pytorch项目,在终端部署。即py文件最终变成exe,可脱离python环境,在任意终端运行。
前端如何向后端发送请求
Requests建立在世界上下载量最大的Python库urllib3上,它令Web请求变得非常简单,功能强大且用途广泛。
上面是get请求,用于从访问的地址中获取信息。还可用post请求,来向后端传入数据
result = requests.post('https://127.0.0.1:8000/detect', data = Data)
输入与输出数据格式与定义,在后端定义,见下文。
以上是通过发送数据所在路径,实现2d检测的一个功能。后端返回检测结果,输入输出都是json即字典格式
注意是在win10的虚拟环境中安装,同样在win10上运行
pip install fastapi
pip install "uvicorn[standard]"
先创建 main.py 文件:
from typing import Optional
from fastapi import FastAPI
#创建FastAPI实例
app = FastAPI()
#创建访问路径
@app.get("/")
def read_root():#定义根目录方法
return {"message": "Hello World"}#返回响应信息
#定义方法,处理请求
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
以上示例共包含两个 get接口,调用任意一个,都会默认执行后续的 def 函数。
在终端中的使用以下命令,来启动服务:
uvicorn main:app --reload
# 注意:--reload 表示让服务器在更新代码后重新启动。仅在开发时使用该选项。
启动服务后,可在前端(如postman中访问localhost/items?=id 来进行测试)
以下是完整的main.py文件,可直接用python执行来启动服务
(重点是其中 post接口以及接收文件的格式定义 )
from typing import Optional
import uvicorn
from fastapi import FastAPI,File
from pydantic import BaseModel
from ml.predict import load_model,Features,predict
#创建FastAPI实例
app = FastAPI()
# 自定义接收数据的结构
class hkk(BaseModel):
file: str
num: int
#创建访问路径
@app.get("/")
def read_root():
return {"message": "Hello World"} # 访问根目录即显示
# 加载模型
models = load_model()
def test(file):
feature = Features(file)
return model.predict(feature)
#调用模型接口
@app.post("/detect/v2")
async def detect2(item: hkk): # async 表示异步执行,hkk为自定义的类
img = item.file
index= item.num
res = test(img)
return {
"filename": file.filename,
"attributes": (len(content),str(type(f)),str(type(content))),
"result": res
}
#运行
if __name__ == '__main__':
uvicorn.run(app, host="127.0.0.1", port=8000)
测试可见前言中 postman截图,传参选 Body> raw> JSON 文件,也可用以下python文件调用:
import requests
url2 = 'http://127.0.0.1:8000/detect/v2'
filename2 = "examples/123.jpg"
files = {
'file':filename2,
'num':int(2)
}
response2 = requests.post(url2, files=files)
print(response2.content)
from fastapi import Body
@app.post("/login")
async def login(data = Body(None)):
return {"data":data} # 除了上述自定义文件类型外,也可采用Body格式
2. 前端传入list 时,在postman 中传参选 Body> form-data ,输入一个list(含两个文件),后端代码:
from fastapi import FastAPI, Header, Body, Form
# 注意要提前 pip install python-multipart
@app.post("/login")
async def login(username= Form(None), password = Form(None)):
return {"data":{"username":username, "password":password}}
3. 返回图片、网页
通过以下三个包,可返回不同类型。
from fastapi.responses import JSONResponse, HTMLResponse, FileResponse
app = FastAPI()
#创建访问路径
@app.get("/user")
def user():
return JSONResponse( content = { "msg": "get user" },
status_code = 202,
headers = { "a": "b" }) # 给返回的header增加新的key:a
@app.get("/")
def user():
html_content = " " "
<html>
<body><p style = "color:red"> Hello World</p></body>
<html>
" " "
return HTMLResponse( content = html_content) # 访问根目录 / 得到设置好的html网页
@app.get("/avater")
def user():
avater = "E:/user/123.jpg"
return FileResponse( avater ,filename = '123.jpg' ) # 访问目录 /avater ,得到下载提示
return FileResponse( avater ) # 只显示图片
jinja2模板 返回HTML (以文件形式导入html)
from fastapi import FastAPI,Request
from fastapi.templating import Jinja2Templates # 需要 pip install jinja2
app = FastAPI()
template = Jinja2Templates ("pages") # 保存 .html 文件的文件夹
@app.get("/")
def user( req: Request ) :
return template.TemplateResponse( "index.html" , content = { "request": req})
①先在 teacher.py 文件中 创建teacher类,用来模拟数据库
from pydantic import BaseModel, Field
class TeacherSchema(BaseModel):
id: int
name: str = Field (default = name, min_length=6) # 规定数据格式
course: None|str = "python 测试" # 旧版: Union[None,str]
salary: float=8000
full_time: bool=True
实例化类的两种方法:
t1 = TeacherSchema (id=3, name=“abc”, salary = “2000”…)
print (t1.dict()) # 返回字典
print (t1.json()) # 返回字符串
data = { “id”: 3 , “name”: “周老师”, “salary”: 90332}
或者从文件导入:
data = load_json(“123.json”)
t1 = TeacherSchema.parse_obj(data)
三种加载方法:
import json
import yaml
def load_json(file):
with open(file, 'r', encoding='utf-8') as fp:
return json.load(fp)
def save_json(data, file):
with open(file, 'w', encoding='utf-8') as fp:
json.dump(data, fp, ensure ascii=False)
def load_yaml(yaml_file) ->Dict: # 定义返回类型
with open(yaml_file, mode ='rb') as fp:
yaml_cont = yaml.load(fp, Loader = yaml.FullLoader)
return yaml_cont
nuitka是一个用来将python代码打包为exe可执行文件,方便其在没有相关环境的windows系统上运行的工具(也支持打包成linux系统下的可执行程序,暂未尝试)。其原理为:将部分python代码(自己写的部分)转换成C代码,以提高运行的速度;import的第三方包不进行编译,在运行时,通过一个python3x.dll的动态链接库 执行第三方包的python代码,通过这样的方式减少exe包的大小。
nuitka 适合将python 编写(基于pyqt5库)的可视化图形界面(GUI)打包,打包速度快,打包完的程序也不大,而 pyinstaller打包的程序一般都非常大,而且运行的速度很慢
环境:
conda 4.7.12
Python 3.6.13
numpy 1.16.4 (容易出错,建议不要高于此版本)
pyqt5 5.15.4
① 下载C编译器:MinGW64 8.1(这个版本最稳定)。
下载地址:https://sourceforge.net/projects/mingw-w64/files
也可使用百度盘:https://pan.baidu.com/share/init?surl=CpdGxZj2hRsU_Z0ukp6kqg#list/path=/
密码8888
其他两个文件保留,是nuitka的附属文件,等会会用
② 将文件3 MinGW64 8.1 解压到C盘,并添加环境变量
③ 打开cmd命令,使用gcc.exe --version测试是否添加上。
pip install nuitka
(1)新建一个简单的python文件,测试运行没有出错
(2)使用nuitka xxx.py命令进行打包。在打包过程中会有提示下载一个包到***\nuitka***这样一个文件夹中,下载进度条可能不动或者很慢,就可以使用 ctrl + C终止进程,手动将百度云下载的文件1解压到提示的这个文件家中
(3)重新使用nuitka xxx.py命令进行打包。还会提示下载另一个包,同样的方式将文件2解压放入
(4)重新使用nuitka xxx.py命令进行打包,这次应该就没问题了
参数作用:
–mingw64 默认为已经安装的vs2017去编译,否则就按指定的比如mingw(官方建议)
–standalone 独立环境,这是必须的(否则拷给别人无法使用)
–windows-disable-console 没有CMD控制窗口
–output-dir=out 生成exe到out文件夹下面去
–show-progress 显示编译的进度,很直观
–show-memory 显示内存的占用
–include-qt-plugins=sensible,styles 打包后PyQt的样式就不会变了
–plugin-enable=qt-plugins 需要加载的PyQt插件
–plugin-enable=tk-inter 打包tkinter模块的刚需
–plugin-enable=numpy 打包numpy,pandas,matplotlib模块的刚需
–plugin-enable=torch 打包pytorch的刚需
–plugin-enable=tensorflow 打包tensorflow的刚需
–windows-icon-from-ico=你的.ico 软件的图标
–windows-company-name=Windows下软件公司信息
–windows-product-name=Windows下软件名称
–windows-file-version=Windows下软件的信息
–windows-product-version=Windows下软件的产品信息
–windows-file-description=Windows下软件的作用描述
–windows-uac-admin=Windows下用户可以使用管理员权限来安装
–linux-onefile-icon=Linux下的图标位置
–onefile 像pyinstaller一样打包成单个exe文件(2021年我会再出教程来解释)
–include-package=复制比如numpy,PyQt5 这些带文件夹的叫包或者轮子
–include-module=复制比如when.py 这些以.py结尾的叫模块
–show-memory 显示内存
–show-progress 显示编译过程
–follow-imports 全部编译
–nofollow-imports 不选,第三方包都不编译
–follow-stdlib 仅选择标准库
–follow-import-to=MODULE/PACKAGE 仅选择指定模块/包编译
–nofollow-import-to=MODULE/PACKAGE 选择指定模块/包不进行编译
完整命令为:
nuitka --standalone --mingw64 --show-progress --show-memory --nofollow-imports --plugin-enable=qt-plugins --include-qt-plugins=sensible,styles --output-dir=out --windows-icon-from-ico=favicon.ico 软件的图标 start.py
// --standalone环境独立
// --mingw64选择之前下载的C编译器
// --show-progress --show-memory显示进度和内存
// --nofollow-imports所有包都不编译
// --plugin-enable=qt-plugins --include-qt-plugins=sensible,styles 添加qt插件,导入相关包
// --output-dir=out --windows-icon-from-ico=favicon.ico 导出路径以及图标
打包完成后会生成一个文件夹,包含xx.build和xx.dist两个目录,前一个无用。后一个就是我们需要的打包好的文件夹,里面有一个exe可执行文件。继续调试添加依赖包:
调试添加包的过程:
(1)在xx.dist目录下打开cmd或者powershell(shift+鼠标右键,点击打开powershell)
(2)运行./xx.exe
(3)查看报错信息,缺少的第三方包就从D:\Anaconda3\envs\myenv(虚拟环境路径)下搜索关键字,将其复制保存到xx.dist目录下。缺少的自己的包,也将其复制过来。一步一步调试,直到把所有的依赖包全都复制到这个目录下,程序完美执行。(记得把这些依赖包复制备份)
(4)之前的命令打包的程序为了调试有一个console黑框框,正式打包的话不要console,在之前的命令中添加–windows-disable-console,具体命令为:
**感谢博主「ha_lee」的原创文章
即将完成