在金融领域,经常需要使用python做模型计算,如果每次发布代码就比较麻烦,所以我们开发了模型配置平台,通过管理控制台来配置,在Flask搭建的python web平台,调用模型文件来实现。模型库文件由python自动下载到服务器,然后执行。网络拓扑图如下:
但是当模型文件很多,外部调用并发高的时候,并发调用会出现有的节点文件并发下载导致下载不全,所以加锁实现,完美解决。代码如下
import importlib
import os
import threading
import traceback
import requests
from flask import Blueprint, request, jsonify, current_app
import resource.config.general_config as config
common_score = Blueprint(name='commomscore', import_name="commomscore", url_prefix='/commomscore')
# 通用的模型执行方法
@common_score.route("/score", methods=["POST"])
def get():
params = request.json
current_app.logger.info(f'- - - request params : {params}')
try:
# 获取模型文件地址
model_file_url = params['common_model_file_url']
# 获取模型文件名称
model_file_name = params['common_model_file_name']
# 模型执行方法名
model_file_method = params['common_model_exec_method']
# 模型文件名,不带后缀
name_arr = model_file_name.split('.')
model_name = name_arr[0]
# 模型文件下载
download(model_file_name, model_file_url)
# 动态加载模型并执行
score = ''
if model_file_name.endswith('.py') or model_file_name.endswith('.so') or model_file_name.endswith('.pyd'):
current_app.logger.info(f'- - - 动态加载模型并执行model_name : {model_name}')
model = importlib.import_module(model_name)
method = getattr(model, model_file_method)
score = method(params)
res = {'code': '200', 'message': 'succeed', 'score': score}
current_app.logger.info(f'- - - response : {res}')
except Exception as e:
err_info = str(traceback.format_exc())
current_app.logger.error(err_info)
if err_info is not None:
res = {'code': '500', 'message': 'failed', "error": str(err_info)}
else:
res = {'code': '500', 'message': 'failed', "error": str(e)}
current_app.logger.info(f'- - - exception response : {res}')
return jsonify(res)
lock = threading.Lock()
# 从oss下载模型文件
def download(model_file_name, model_file_url):
dir_exist = os.path.exists(config.MODEL_PATH)
if not dir_exist:
os.makedirs(config.MODEL_PATH)
# 完整模型文件路径
fullpath = config.MODEL_PATH + "/" + model_file_name
# 判断模型文件是否存在
file_exist = os.path.exists(fullpath)
if not file_exist:
# 加锁
try:
lock.acquire()
file_exist = os.path.exists(fullpath)
if file_exist:
lock.release()
return
# 文件不存在则进行文件下载
r = requests.get(model_file_url)
# 保存
with open(fullpath, 'wb') as f:
current_app.logger.info(f'- - - 模型目录文件不存在,创建文件 : {fullpath}')
f.write(r.content)
f.close()
except Exception as e:
raise e
finally:
lock.release()