def same_images_clean(collection_id): """图片去重处理""" from DataSet.rabbitMQ.task_queue_client import same_images_clean_task with app.app_context(): images_path_list = list() images = None try: images = Image.query.filter(Image.collection_id == collection_id, Image.status < 2).all() except Exception as e: current_app.logger.error(e) if not images: return 'no images' for image in images: # print(image) # print(fun.getInfo(image.site)) image_site = current_app.config['NGINX_SITE'] + fun.getInfo( image.site)['group_file_id'] images_path_list.append(image_site) # 队列开启 response_image_list = same_images_clean_task(images_path_list) # 解析队列返回的josn数据 response_image_list = json.loads(response_image_list) delete_imglist = response_image_list[1] imgList = response_image_list[0] # 删除数据库重复图片 if delete_imglist: for i in delete_imglist: i = str(i).split('/', 4)[4] delete_image = Image.query.filter_by(site=i).first() fun.remove(delete_image.label_path) # 删除本地存储的标签文件 try: db.session.delete(delete_image) db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback() fun.remove(i) # 删除本地存储的图片 # 修改去重后的图片状态为待标注 ch_img = list(set(imgList).difference(set(delete_imglist))) for i in ch_img: i = str(i).split('/', 4)[4] change_state = Image.query.filter_by(site=i).first() try: change_state.status = 1 # 代表待标注状态的数字 db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback()
def delete_data(): """ 删除数据集 :return: """ local_time = time.time() user_data = request.get_json() if not user_data: return jsonify(err_no=RET.PARAMERR, err_desc='参数缺失') name = user_data.get('name') if not name: return jsonify(err_no=RET.PARAMERR, err_desc='参数缺失') try: collection = Collection.query.filter_by(user_id=g.user.id, name=name).first() if collection.images: for i in collection.images: if i.site: fun.remove(i.site.encode()) if i.label_path: fun.remove(i.label_path.encode()) db.session.delete(i) db.session.commit() if collection.labels: for i in collection.labels: db.session.delete(i) db.session.commit() db.session.delete(collection) db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback() return jsonify(err_no=RET.DBERR, err_desc='信息保存异常') request_id = (request.cookies.get('session'))[:36] time_used = int((time.time() * 1000) - int(local_time * 1000)) return jsonify(err_no=RET.OK, err_desc='OK', request_id=request_id, time_used=time_used )
def preprocessing(collection_id, label_info): """预标注任务""" from DataSet.rabbitMQ.task_queue_client import preprocessing_task with app.app_context(): # 开辟一个上下文管理空间 # get config model = -1 pre_model = list() label_name_list = list() c_label_name_list = list() for key in label_info: model = int(key.split('_')[0]) pre_model.append(int(key.split('_')[1])) for k in label_info[key]: label_name_list.append(label_info[key][k]) c_label_name_list.append(k) images = None try: images = Image.query.filter_by(collection_id=collection_id, status=1).all() except Exception as e: current_app.logger.error(e) if not images: print(label_info, 'no images') for image in images: # get image url image_obj = Image.query.filter_by(id=image.id).first() image_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image_obj.site)['group_file_id'] file = urllib2.urlopen(image_url_path) # 获取图片 # get image file tmpIm = cStringIO.StringIO(file.read( )) # Return a StringIO-like stream for reading or writing img = image_pil.open(tmpIm) # PIL模块处理图像 if img.mode in ('RGBA', 'LA', 'P'): background = image_pil.new('RGB', img.size) background.paste(img) img = background # base64 bs = BytesIO() img.save(bs, format="JPEG") b64 = base64.b64encode(bs.getvalue()) # get request type_b64_list = list() type_b64_list.append(b64) type_b64_list.append(model) type_b64_list.append(pre_model) # request json_data = preprocessing_task(type_b64_list) # 指定预处理队列处理 json_data = json.loads(json_data) # print( 'label results ', json_data ) # get label label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image_obj.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_data = tmpIm.read() label_json_data = json.loads(label_data) # print( 'old label_json_data ', label_json_data ) isSuccess = False # 模型1 if model == 1: labels = list() for key in json_data: labels = labels + json_data[key]['labels'] for label_dict in labels: if label_dict['content'] in c_label_name_list: label_name = label_name_list[c_label_name_list.index( label_dict['content'])] label = Label.query.filter_by( collection_id=collection_id, name=label_name).first() # 创建要保存的标签字典 classification = dict() classification['category_id'] = label.label_id classification['category_name'] = label_name label_json_data['classification'] = classification label.count += 1 isSuccess = True else: print('other label: ', label_dict['content']) # 模型2 elif model == 2: detection = list() for key in json_data: detection = detection + json_data[key]['detection'] for label_dict in detection: pmid = label_dict['pre_model'] if float(label_dict['score']) > 0.3: AI_label_name = AI_label_list[pmid][ label_dict['label_id']].decode('utf-8') # print( 'c_label_name_list', AI_label_name, c_label_name_list ) if AI_label_name in c_label_name_list: label_name = label_name_list[ c_label_name_list.index(AI_label_name)] label = Label.query.filter_by( collection_id=collection_id, name=label_name).first() # 标注框坐标转换 bbox_list = list() bbox_list.append('%.2f' % (float(label_dict['xmin']))) bbox_list.append('%.2f' % (float(label_dict['ymin']))) bbox_list.append('%.2f' % (float(label_dict['xmax']) - float(label_dict['xmin']))) bbox_list.append('%.2f' % (float(label_dict['ymax']) - float(label_dict['ymin']))) # 创建json annotation字典 annotation = dict() annotation['bbox'] = bbox_list annotation['category_id'] = label.label_id annotation['category_name'] = label.name annotation['segmentation'] = [] if 'feaData' in label_dict: annotation['feaData'] = label_dict['feaData'] label_json_data['annotation'].append(annotation) label.count += 1 isSuccess = True if isSuccess: # print( 'label_json_data', label_json_data ) label_data = json.dumps(label_json_data) # 保存修改后的json文件 new_label_path = fun.upload(label_data, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) # 修改数据库json文件存储路径 image_obj.label_path = new_label_path['filename'] # 修改图片状态 image_obj.status = 2 db.session.commit() else: image_obj.status = 2 db.session.commit()
def classification(status, table_site, upload_image_site, collection, label_name): """ 分类/人脸 :param status: 状态,----lmz改-》标注 :param table_site: 对应表文件 :param upload_image_site: 图片文件 :param collection: 集合id :param label_name: 标签集合 :return: """ with app.app_context(): collections = Collection.query.filter_by(id=collection).first() table_list = [] error_list = [] for file_name, up_file in upload_image_site.items(): up_file = base64.b64decode(up_file) images = storage(up_file, collections, file_name) size = image_size(up_file) if status == 'appoint_table': # 对应表 if table_site is None: return '{"err_no": "1", "err_desc": "参数缺失"}' try: if not table_list: for i in table_site.split('\r\n'): table_list.append(i.split(':')[0]) tables = table_site.split(file_name + ':')[1] labels = Label.query.filter_by( name=tables.split('\r\n')[0]).first() if file_name in table_list and labels is not None: # 标注上传 clf.classification(images, size, labels.label_id, labels.name) else: clf.default(images, size) except Exception as e: fun.remove(images.site) current_app.logger.error(e) error_list.append(e) elif status == 'default': # 未标注 if not upload_image_site: return '{"err_no": "1", "err_desc": "参数缺失"}' try: clf.default(images, size) except Exception as e: current_app.logger.error(e) fun.remove(images.site) error_list.append(e) elif status.split(':')[1] in label_name: # 标注上传 try: label_data = Label.query.filter_by( collection_id=collection, label_id=status.split(':')[0]).first() if label_data is None: return '{"err_no": "1", "err_desc": "没有此标签"}' if not upload_image_site: return '{"err_no": "1", "err_desc": "参数缺失"}' if status.split(':')[1] != label_data.name: return '{"err_no": "1", "err_desc": "错误的标签ID"}' clf.classification(images, size, status.split(':')[0], status.split(':')[1]) except Exception as e: fun.remove(images.site) current_app.logger.error(e) error_list.append(e) db.session.delete(images) db.session.commit() else: fun.remove(images.site) db.session.delete(images) db.session.commit() same_images_clean(collection) return '{"err_no": "0", "err_desc": "OK", "上传张数": "%s", "失败张数": "%s", "错误名称": "%s"}' % \ (len(upload_image_site), len(error_list), error_list)
def delete_set(uid, name): """ 数据集删除 :param uid: 用户id :param name: 数据集名称 :return: """ from DataSet.rabbitMQ.task_queue_client import delete_set_task with app.app_context(): try: collection = Collection.query.filter_by(user_id=uid, name=name).first() if collection.images: for i in collection.images: if i.site: fun.remove(i.site) if i.label_path: fun.remove(i.label_path) db.session.delete(i) db.session.commit() if collection.labels: for i in collection.labels: db.session.delete(i) db.session.commit() if collection.versions: for i in collection.versions: db.session.delete(i) db.session.commit() # 以下 user = User.query.filter_by(id=uid).first() share_users = user.share my_share = share_users.my_share # 我的分享 str if my_share: # 队列开启 task_my_share = delete_set_task(my_share) dict_my_share = eval(task_my_share) data_dict = {} for key, value in dict_my_share.items(): for i in value: if i == collection.id: value.remove(i) data_dict[key] = value if not value: del dict_my_share[key] Share.query.filter_by(id=uid).update({ 'my_share': json.dumps(data_dict) if dict_my_share else None }) db.session.commit() for data_id, data_info in data_dict.items(): Share.query.filter_by(id=data_id).update({ 'share_collection': json.dumps(data_info) if data_info else None }) db.session.commit() db.session.delete(collection) db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback() return '{"err_no": "2", "err_desc": "信息保存异常", "data": %s}' % e return '{"err_no": "0", "err_desc": "OK"}'
def delete_version(status, version_id): """ 版本删除 :param status: 状态 :param version_id: 版本id :return: """ from DataSet.rabbitMQ.task_queue_client import delete_version_task # 查出版本下原有图片json路径 减掉对应label次数, 删除该版本的压缩包 with app.app_context(): # 以下是队列内容 versions = Version.query.filter_by(id=version_id).one() if versions.zip_path: fun.remove(versions.zip_path) label_dict = {} number = 0 for image in versions.images: label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] label_url_path = delete_version_task(label_url_path) files = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(files.read()) label_data = tmpIm.read() label_json_data = json.loads(label_data) if 1 == versions.collection.type: json_label_id = label_json_data['classification'][0][ 'category_id'] if json_label_id in label_dict: label_dict[json_label_id] += 1 else: label_dict[json_label_id] = 1 elif 2 == versions.collection.type: number += len(label_json_data['annotation']) for i in label_json_data['annotation']: json_label_id = i['category_id'] if json_label_id in label_dict: label_dict[json_label_id] += 1 else: label_dict[json_label_id] = 1 for label_id, label_count in label_dict.items(): # 标签中每个标签的使用量 old_count = db.session.query(Label.count).filter( Label.label_id == label_id, Label.collection_id == versions.collection.id).scalar() # 当前标签 label = Label.query.filter_by( label_id=label_id, collection_id=versions.collection.id).first() # 更新当前标签使用量为 新+旧 if (old_count - label_count) < 0: label.count = 0 else: label.count = old_count - label_count # 将标签id 名字使用量存入字典 db.session.commit() # 以上是队列内容 if status == 'delete': for image in versions.images: image.version_id = None db.session.add(image) db.session.commit() db.session.delete(versions) db.session.commit() elif status == 'delete_all': for image in versions.images: if image.site: fun.remove(image.site.encode()) if image.label_path: fun.remove(image.label_path.encode()) db.session.delete(image) db.session.commit() db.session.delete(versions) db.session.commit() else: current_app.logger.info('错误参数{}'.format(status)) return '{"err_no": "2", "err_desc": "参数有误"}' return '{"err_no": "0", "err_desc": "OK"}'
def detection(table_site, upload_image_site, label_file, collection): """ 检测/分割 :param table_site: 对应表 :param upload_image_site: 图片 :param label_file: 标注文件 :param collection: 集合id :return: """ with app.app_context(): collection_id = collection collection = Collection.query.filter_by(id=collection).first() label_file_name = [] # 标注列表名,有后缀 label_list = [] # 标注列表名,无后缀 if upload_image_site and label_file: for l_file in label_file: label_file_name.append(l_file) label_list.append(l_file.split('.')[0]) table_name_list = [] # 对应表,图片名 table_file_list = [] # 对应表,标注文件名 error_list = [] method = 'default' for file_name, up_file in upload_image_site.items(): up_file = base64.b64decode(up_file) images = storage(up_file, collection, file_name) size = image_size(up_file) if all([table_site, upload_image_site, label_file, collection]): method = 'ap_table' # 对应表 try: if not all([table_name_list, table_file_list]): for i in table_site.split('\r\n'): table_name_list.append(i.split(':')[0]) table_file_list.append(i.split(':')[1]) if file_name in table_name_list and \ table_site.split(file_name + ':')[1].split('\r\n')[0] in label_file_name: tagging_function(file_name, label_file, images, size, collection) else: clf.default(images, size) except Exception as e: fun.remove(images.site) current_app.logger.error(e) error_list.append(e) elif all([upload_image_site, label_file, collection]): method = 'label' # 已经标注上传,未选择对应表 try: if file_name.split('.')[0] in label_list: tagging_function(file_name, label_file, images, size, collection) else: clf.default(images, size) except Exception as e: fun.remove(images.site) current_app.logger.error(e) error_list.append(e) elif all([upload_image_site, collection]): method = 'no_label' # 未标注 try: clf.default(images, size) except Exception as e: fun.remove(images.site) current_app.logger.error(e) error_list.append(e) else: return '{"err_no": "1", "err_desc": "参数缺失"}' same_images_clean(collection_id) return '{"err_no": "0", "err_desc": "OK", "上传张数": "%s", "失败张数": "%s", "错误名称": "%s", "method":"%s"}' % \ (len(upload_image_site), len(error_list), error_list, method)
def save_label(): """标注保存""" data = request.get_json() state = data.get('classification') collection_id = data.get('collection_id') collection_type = Collection.query.filter_by(id=collection_id).first().type # 分类/人脸识别标注 if state: label_id = state['category_id'] category_name = state['category_name'] if category_name is not None: try: label = Label.query.filter_by(collection_id=collection_id, label_id=label_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') # 创建要保存的标签字典 classification = dict() classification['category_id'] = label_id classification['category_name'] = category_name image_site = data.get('image') try: image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() except: current_app.logger.error(image_site) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if image.status == 3: return jsonify(err_no=RET.NODATA, err_desc='请勿重复标记分类图片') label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) label_json_date['classification'] = [classification] label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) # 修改数据库json文件存储路径 image.label_path = new_label_path['filename'] # 修改图片状态 if collection_type == 1: pass # image.status = 3 label.count += 1 db.session.commit() else: return jsonify( err_no=RET.PARAMERR, err_desc='参数缺失', ) # 检测/分割标注 state = data.get('annotation') if state: for label_dict in data.get('annotation'): category_id = label_dict['category_id'] category_name = label_dict['category_name'] bbox = label_dict['bbox'] segmentation = label_dict['segmentation'] if category_name and bbox is not None: try: label = Label.query.filter_by( collection_id=collection_id, label_id=category_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') try: for num in bbox: num = float(num) if math.isnan(num): current_app.logger.error(num) return jsonify(err_no=RET.DBERR, err_desc='参数错误') except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='参数错误') # 创建要保存的标签字典 annotation = dict() annotation['bbox'] = bbox annotation['category_id'] = category_id annotation['category_name'] = category_name annotation['segmentation'] = segmentation image_site = data.get('image') image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) label_json_date['annotation'].append(annotation) label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) # 修改数据库json文件存储路径 image.label_path = new_label_path['filename'] # 修改图片状态 if collection_type == 2: pass # image.status = 3 label.count += 1 db.session.commit() else: return jsonify(err_no=RET.PARAMERR, err_desc='参数缺失') return jsonify(err_no=RET.OK, err_desc='标注成功')
def delete_label(): """删除标签""" data = request.get_json() state = data.get('classification') collection_id = data.get('collection_id') if state: label_id = state['category_id'] try: label = Label.query.filter_by(collection_id=collection_id, label_id=label_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') image_site = data.get('image') image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) old_label_name = label_json_date['classification'][0]['category_name'] old_label = Label.query.filter_by(collection_id=collection_id, name=old_label_name).first() old_label.count -= 1 del label_json_date['classification'][0] label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) image.label_path = new_label_path['filename'] db.session.commit() # 检测/分割标注 for label_dict in data.get('annotation'): category_id = label_dict['category_id'] print('label_dict', label_dict) old_bbox = label_dict['old_bbox'] old_bbox = [float(d) for d in old_bbox.split(',')] try: label = Label.query.filter_by(collection_id=collection_id, label_id=category_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') image_site = data.get('image') image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) for label_json_dict in label_json_date['annotation']: bbox = [float(d) for d in label_json_dict['bbox']] if bbox == old_bbox: print('old_bbox = ', old_bbox) old_label_id = label_dict['category_id'] old_label = Label.query.filter_by( collection_id=collection_id, label_id=old_label_id).first() old_label.count -= 1 label_json_date['annotation'].remove(label_json_dict) label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) # 修改数据库json文件存储路径 image.label_path = new_label_path['filename'] db.session.commit() return jsonify(err_no=RET.OK, err_desc='删除成功')
def change_label(): """改变标签""" data = request.get_json() state = data.get('classification') collection_id = data.get('collection_id') if state: label_id = state['category_id'] category_name = state['category_name'] if category_name is not None: try: label = Label.query.filter_by(collection_id=collection_id, label_id=label_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') classification = dict() classification['category_id'] = label_id classification['category_name'] = category_name image_site = data.get('image') image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) old_label_name = label_json_date['classification'][0][ 'category_name'] old_label = Label.query.filter_by(collection_id=collection_id, name=old_label_name).first() old_label.count -= 1 del label_json_date['classification'][0] label_json_date['classification'].append(classification) label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) image.label_path = new_label_path['filename'] label.count += 1 db.session.commit() else: return jsonify(err_no=RET.PARAMERR, err_desc='参数缺失') # 检测/分割标注 for label_dict in data.get('annotation'): category_id = label_dict['category_id'] category_name = label_dict['category_name'] print(label_dict) bbox = label_dict['bbox'] old_bbox = label_dict['old_bbox'] segmentation = label_dict['segmentation'] if category_name and bbox and segmentation and old_bbox is not None: try: label = Label.query.filter_by(collection_id=collection_id, label_id=category_id).first() except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='查询失败') if not label: return jsonify(err_no=RET.NODATA, err_desc='没有该标签') try: for num in bbox: if not num.isnumeric(): current_app.logger.error(str(num)) return jsonify(err_no=RET.DBERR, err_desc='参数错误') num = float(num) except Exception as e: current_app.logger.error(e) return jsonify(err_no=RET.DBERR, err_desc='参数错误') # 创建要保存的标签字典 annotation = dict() annotation['bbox'] = bbox annotation['category_id'] = category_id annotation['category_name'] = category_name annotation['segmentation'] = segmentation image_site = data.get('image') image = Image.query.filter_by( site=str(image_site).split('/', 4)[4]).first() label_url_path = current_app.config['NGINX_SITE'] + fun.getInfo( image.label_path)['group_file_id'] # 读取json文件内容 file = urllib2.urlopen(label_url_path) tmpIm = cStringIO.StringIO(file.read()) label_date = tmpIm.read() label_json_date = json.loads(label_date) for label_json_dict in label_json_date['annotation']: if label_json_dict['bbox'] == old_bbox: old_label_name = label_dict['category_name'] old_label = Label.query.filter_by( collection_id=collection_id, old_label_name=old_label_name).first() old_label.count -= 1 label_json_date['annotation'].remove(label_json_dict) label_json_date['annotation'].append(annotation) label_date = json.dumps(label_json_date) # 保存修改后的json文件 new_label_path = fun.upload(label_date, file_ext_name='json') # 删除原json文件 fun.remove(image.label_path) # 修改数据库json文件存储路径 image.label_path = new_label_path['filename'] label.count += 1 db.session.commit() else: return jsonify(RET.PARAMERR, err_desc='参数缺失') return jsonify(err_no=RET.OK, err_desc='修改成功')