基於flask-gunicorn的算法部署框架介紹
此demo是爲了讓大家快速地部署flask框架,把自己的算法部署到計算能力更好的服務器上。是一個面向移動client—服務器server的簡易科研數據分析平臺。
相關鏈接
【搭建屬於你的科研平臺】(一)基於flask的服務器端算法框架搭建
基礎介紹
- Flask :python最流行的兩個框架之一
(django、flask)
,輕量級是最大的特點。ps: 知乎用tornado+SQLAlchemy
開發,也是基於python的web框架 - Gunicorn:只熟悉熟悉用 java 或者 PHP 做開發的同學可能對 python 的部署一開始不太理解,Flask應用是一個符合WSGI規範的Python應用,不能獨立運行(類似app.run的方式僅適合開發模式),需要依賴其他的組件提供服務器功能。
- gevent:Gunicorn 默認使用同步阻塞的網絡模型
(-k sync)
,對於大併發的訪問可能表現不夠好,我們很方便地順手套一個gevent來增加併發量
demo講解
flask框架有兩種官方的組織方式,一種是基於blueprint
的,其啓動文件app.py
如下所示
from project import create_app #從project文件夾中的__init__.py中導入create_app函數
app = create_app() #記住這裏的變量名app
if __name__ == '__main__':
app.run(debug=True)
本demo中用的是新手常用版,對於我們科研場景中不需要響應數個api的情況而言,無需用blueprint的方法來科學地管理不同的api響應類、方法。如下所示:
from flask import Flask
app = Flask(__name__) #記住這裏的變量名app
@app.route('/')
def hello():
return 'hello docker&flask'
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
注意:該方法下,gunicorn.py和flask的項目文件同級。
Directory : demo
1. demo/app.py
import os
import time
from flask import request, Flask, jsonify
from werkzeug.serving import WSGIRequestHandler
from logger.fastlogger import getloggerfast
from demo.pdwrap import PdWrapper
logger = getloggerfast(__name__)
app = Flask(__name__)
dataexecuter = PdWrapper()
UPLOAD_FOLDER = '../storage'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # 設置文件上傳的目標文件夾
basedir = os.path.abspath(os.path.dirname(__file__)) # 獲取當前項目的絕對路徑
@app.route('/')
def hello_world():
return 'Welcomes to Demo Cloud Platform supported by github: https://github.com/LetterLi1997'
@app.route('/api/upload', methods=['GET','POST'], strict_slashes=False)
def api_upload():
global result_done, is_processing, upload_done
upload_done = False
if request.method == 'POST':
file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER']) # 拼接成合法文件夾地址
print(file_dir)
if not os.path.exists(file_dir):
os.makedirs(file_dir) # 文件夾不存在就創建
f=request.files['myfile'] # 從表單的file字段獲取文件,myfile爲該表單的name值
if f:
fname=f.filename
ext = fname.rsplit('.', 1)[1] # 獲取文件後綴
# unix_time = int(time.time())
# new_filename = str(unix_time)+'.'+ext # 修改文件名
f.save(os.path.join(file_dir, fname)) #保存文件到upload目錄
upload_done = True
print('上傳成功-----result_done:{}, is_processing:{}, upload_done:{}'.format(result_done, is_processing, upload_done))
'''
這裏調用算法處理函數
eg. time.sleep(15) #算法處理時長爲15s
'''
return jsonify({"errno": 0, "errmsg": "上傳成功"})
else:
print('上傳失敗')
upload_done = False
return jsonify({"errno": 1001, "errmsg": "上傳失敗"})
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
這是最重要的入口文件。能夠攔截下手機app上傳的POST數據,將上傳的文件存儲到storage
文件夾中。
2. demo/pdwrap.py
這裏是用於封裝個人的算法,給出了一個例子~ 技術大佬多多指教哈,可能大家平時做科研的時候比較追求效率,代碼的結構上不會非常注意。本人蔘考了一些開源代碼的好習慣,用類來封裝這個算法。
3. demo/identityAuth.py
這裏是具體的算法實現,在pdwrap.py中可以調用具體的代碼,這樣整體的框架就會比較清晰。
logger
這個文件夾是爲了良好的習慣,可將post等訪問請求、算法分析的結構等保存到run.log中。
model
這個文件用來存放神經網絡、機器學習的模型
storage
該路徑存放app上傳文件,demo中的算法取storage中的文件進行處理。
這篇文章預提供簡易版的backend例程。
附錄
注意點:flask 包導入的問題:如果沒有寫過多層級的flask模塊,大家可能在文件分層管理會遇到一些困難。 Python在不同目錄下導入模塊的方法
因爲直接run flask的app.py
和gunicorn demo.app:app -c gunicorn.conf.py
是不一樣的。
1. python demo/app.py
其中app.py位於demo目錄之下,因此此種方案需要改寫幾處代碼:
- demo/app.py
import sys
from flask import request, Flask, jsonify
from werkzeug.serving import WSGIRequestHandler
#notice1: don't use "/path/to/demo-backend/demo"
sys.path.append("/path/to/demo-backend") # project root
#notice2: don't use demo.demowrap, but you should use logger.fasterlogger.
# it has been clearly demonstrated in
# (https://blog.csdn.net/zhili8866/article/details/52980924)
from logger.fastlogger import getloggerfast
from demowrap import DemoWrapper
- demo/demowrap.py
import sys
#notice1: don't use "/path/to/demo-backend/demo"
sys.path.append("/path/to/demo-backend") # project root
#notice2: don't use demo.identityAuth, because they are in the same parent directory: demo/
from logger.fastlogger import getloggerfast
from identityAuth import identityAuth
2. gunicorn demo.app:app -c gunicorn.conf.py
其中app.py位於項目根目錄之下
#notice1: must use demo.identityAuth
from logger.fastlogger import getloggerfast
from demo.demowrap import DemoWrapper