diff --git a/blender/fill_dm_code.py b/blender/fill_dm_code.py index 93edb09..b04df1b 100644 --- a/blender/fill_dm_code.py +++ b/blender/fill_dm_code.py @@ -1,6 +1,7 @@ import os, sys, bpy, math, time, platform, cairosvg, ppf.datamatrix, shutil, requests, json, redis, oss2, cv2,qrcode from retrying import retry import subprocess +import multiprocessing import random import numpy as np import matplotlib.pyplot as plt @@ -403,238 +404,212 @@ def remove_gray_and_sharpening(jpg_path): # show_histogram(input_image, img_id, low_x_thresh, high_x_thresh) cv2.imwrite(jpg_path, high_output_image, [cv2.IMWRITE_JPEG_QUALITY, 95]) # 保存图片的质量是原图的 95% -def main(workdir, r, print_id): - print('脚底板二维码程序开始运行...') - only_one = False - while True: - #随机休眠 1- 9 - time.sleep(random.uniform(1, 9)) - if print_id == '0': - try: - if r.llen('model:foot') == 0: - # print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '队列为空,5秒后重试') - time.sleep(5) - continue - except Exception as e: - print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试') - print(e) - time.sleep(5) - r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6) - # r = redis.Redis(host='172.31.1.254', password='', port=6379, db=6) - # continue - # 打印队列里面的全部内容 - print(f'当前model:foot队列长度:{r.llen("model:foot")}') - for i in r.lrange('model:foot', 0, -1): - print(i) - print_id = r.lpop('model:foot') - if print_id is None: - print_id = '0' - continue - #判断是否存在相同的值 - isHaveAlready = 0 - for i in r.lrange('model:foot', 0, -1): - if i == print_id: - isHaveAlready = 1 - - if isHaveAlready == 1: - print_id = '0' - continue - print_id = print_id.decode('utf-8') - else: - print(f'接收到运行一个{print_id}任务') - only_one = True - - res = requests.get(f'{get_pid_by_printid_url}?print_id={print_id}') - print('获取pid:', f'{get_pid_by_printid_url}?print_id={print_id}', res.text) - resCode = json.loads(res.text)['code'] - #该笔订单的获取信息有误,可能信息还没有成功 - if int(resCode) != 1000: - tempMesg = json.loads(res.text)['message'] - #判断是否包含 不存在 - if tempMesg == "打印订单不存在": - print(f"打印ID{print_id}打印订单不存在,跳过") - # res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') - os.system(f'blender -b -P fill_dm_code.py') - return - - print("获取打印任务信息有问题,重新任务队列,打印id-",print_id,"重新执行脚底板任务,等待20s") - time.sleep(20) - #将pid 重新扔进队列 - r.lpush("model:foot", print_id) - #重新调用脚底板程序 +#获取该笔订单的信息,判断是否存在,不存在就跳过 +def getInfoByPrintId(print_id): + res = requests.get(f'{get_pid_by_printid_url}?print_id={print_id}') + print('获取pid:', f'{get_pid_by_printid_url}?print_id={print_id}', res.text) + resCode = json.loads(res.text)['code'] + #该笔订单的获取信息有误,可能信息还没有成功 + if int(resCode) != 1000: + tempMesg = json.loads(res.text)['message'] + #判断是否包含 不存在 + if tempMesg == "打印订单不存在": + print(f"打印ID{print_id}打印订单不存在,跳过") + # res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') #os.system(f'blender -b -P fill_dm_code.py') - continue - use_foot_type = json.loads(res.text)['data']['use_foot_type'] - pid = json.loads(res.text)['data']['pid'] - order_id = json.loads(res.text)['data']['order_id'] - - filename = os.path.join(workdir, f'{pid}_{order_id}', find_obj(pid, order_id)) - print('导入obj文件:', filename) - # return - if only_one: - print(f'接收到运行一个{print_id}任务,强制调用cal_foot_position.py计算并上传qr_position') - os.system(f'blender -b -P cal_foot_position.py -- {pid}_{order_id}_{print_id}') - print("延时20s,等待计算脚底板坐标") - time.sleep(20) - res = requests.get(f'{get_qr_position_url}?print_id={print_id}') - print('从云端获取的qr_position1:', res.text) - codeTemp = json.loads(res.text)['code'] - if str(codeTemp) == "-1": - #移除该脚底板的面积处理 - res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') - os.system(f'blender -b -P fill_dm_code.py') - return - qr_position = json.loads(res.text)['data']['position_data'] - else: - #从云端获取qr_position,如果获取为空,调用cal_foot_position.py计算并上传qr_position,再重新读取qr_position.txt - res = requests.get(f'{get_qr_position_url}?print_id={print_id}') - print('从云端获取的qr_position2:', res.text) + return False - codeTemp = json.loads(res.text)['code'] - if str(codeTemp) == "-1": - continue - - qr_position = json.loads(res.text)['data']['position_data'] - print("云端获取的坐标数据",qr_position) - if qr_position == '': - time.sleep(3) - print('qr_position为空,调用cal_foot_position.py计算并上传qr_position') - os.system(f'blender -b -P cal_foot_position.py -- {pid}_{order_id}_{print_id}') - print("延时20s,等待计算脚底板坐标") - time.sleep(20) - res = requests.get(f'{get_qr_position_url}?print_id={print_id}') - print('从云端获取的qr_position3:', res.text) - qr_position = json.loads(res.text)['data']['position_data'] - else: - qr_position = json.loads(qr_position) - - if qr_position == "": - print("获取脚底坐标数据为空,重新任务队列,打印id-",print_id,"重新执行脚底板任务") - #将pid 重新扔进队列 - r.lpush("model:foot", print_id) - #重新调用脚底板程序 - #os.system(f'blender -b -P fill_dm_code.py') - continue + print("获取打印任务信息有问题,重新任务队列,打印id-",print_id,"重新执行脚底板任务,等待20s") + time.sleep(20) + #将pid 重新扔进队列 + r.lpush("model:foot", print_id) + return False + return res.text + +#获取订单的坐标信息,判断是否有,没有的话就重新生成坐标信息 +def getQrPosition(print_id): + #从云端获取qr_position,如果获取为空,调用cal_foot_position.py计算并上传qr_position,再重新读取qr_position.txt + res = requests.get(f'{get_qr_position_url}?print_id={print_id}') + print('从云端获取的qr_position1:', res.text) + codeTemp = json.loads(res.text)['code'] + if str(codeTemp) == "-1": + print(f"获取打印ID{print_id}的脚底板坐标失败,进行下一笔订单的处理") + return False + qr_position = json.loads(res.text)['data']['position_data'] + if qr_position == '': + print(f"pid={pid},打印id={print_id} order_id={order_id},云端获取的坐标数据为空,进行重新计算") + time.sleep(3) + print('qr_position为空,调用cal_foot_position.py计算并上传qr_position') + os.system(f'blender -b -P cal_foot_position.py -- {pid}_{order_id}_{print_id}') + print("延时20s,等待计算脚底板坐标") + time.sleep(20) + res = requests.get(f'{get_qr_position_url}?print_id={print_id}') + print(f"pid={pid},打印id={print_id} order_id={order_id},重新获取qr_position",res.text) + print('从云端获取的qr_position3:', res.text) + if str(json.loads(res.text)['code']) == "-1": + print(f"pid={pid},打印id={print_id} order_id={order_id},重新获取qr_position 失败",res.text) + return False + qr_position = json.loads(res.text)['data']['position_data'] + if qr_position == '': + #跳过该笔订单 + print(f"pid={pid},打印id={print_id} order_id={order_id},重新获取qr_position 为空,跳过脚底板的处理,执行下一笔任务") + #移除该脚底板的面积处理 + res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') + return False + else: + qr_position = json.loads(qr_position) - if type(qr_position) == str: qr_position = json.loads(qr_position) - print(f'type of qr_position:{type(qr_position)}') - print(f'qr_position:{qr_position}') + if qr_position == "": + print("获取脚底坐标数据为空,重新任务队列,打印id-",print_id,"重新执行脚底板任务") + #将pid 重新扔进队列 + r.lpush("model:foot", print_id) + return False + + return qr_position - qr_position['location'][2] = -0.1 +def main(workdir, r, print_id): + + resText = getInfoByPrintId(print_id) + print(f"根据打印ID{print_id}获取订单信息-内容{resText}") + if resText == False: + print(f"根据打印ID{print_id}获取订单信息失败") + return + arrResText = json.loads(resText) + #订单的相关信息 + use_foot_type = arrResText['data']['use_foot_type'] #构建类型 + pid = arrResText['data']['pid'] #pid + order_id = arrResText['data']['order_id'] # order_id + + #文件路劲 + filename = os.path.join(workdir, f'{pid}_{order_id}', find_obj(pid, order_id)) + print('导入obj文件:', filename) + + #获取该笔订单的坐标 + qr_position = getQrPosition(print_id) + if qr_position == False: + return + + if type(qr_position) == str: qr_position = json.loads(qr_position) + print(f'type of qr_position:{type(qr_position)}') + print(f'qr_position:{qr_position}') + + qr_position['location'][2] = -0.1 + + temp_foot_data = print_id + # 根据print_id生成qr码 + qr_path = os.path.join(workdir, f'{pid}_{order_id}' ,'qr.png') + # if use_foot_type == "short_url": + # #调用接口获取短网址信息 + # short_url = get_short_url(print_id) + # if short_url == False: + # return + # temp_foot_data = short_url + # print(f'temp_foot_data---{temp_foot_data}') + gen_data_matrix(print_id,pid, qr_path) + #休眠1秒 + time.sleep(2) + #判断是否存在 qr_path,不存在就执行下一个任务 + if not os.path.exists(qr_path): + #移除该脚底板的面积处理 + print(f"pid={pid},打印id={print_id} order_id={order_id},生成的二维码为空,跳过脚底板的处理,执行下一笔任务") + res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') + #os.system(f'blender -b -P fill_dm_code.py') + return + + #在blender中贴上脚底板二维码的信息 + + # 导入obj文件,重置到标准单位 + bpy.ops.wm.read_homefile() + bpy.context.preferences.view.language = 'en_US' + bpy.ops.object.delete(use_global=False, confirm=False) + bpy.context.scene.unit_settings.scale_length = 0.001 + bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' + bpy.context.scene.unit_settings.mass_unit = 'GRAMS' + + bpy.ops.import_scene.obj(filepath=filename) + #bpy.ops.wm.obj_import(filepath=filename) + obj = bpy.context.selected_objects[0] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) - temp_foot_data = print_id - # 根据print_id生成qr码 - qr_path = os.path.join(workdir, f'{pid}_{order_id}' ,'qr.png') - # if use_foot_type == "short_url": - # #调用接口获取短网址信息 - # short_url = get_short_url(print_id) - # if short_url == False: - # return - # temp_foot_data = short_url - # print(f'temp_foot_data---{temp_foot_data}') - gen_data_matrix(print_id,pid, qr_path) - #休眠1秒 - time.sleep(1) - #判断是否存在 qr_path,不存在就执行下一个任务 - if not os.path.exists(qr_path): - #移除该脚底板的面积处理 - res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') - os.system(f'blender -b -P fill_dm_code.py') - return + pid_objname = find_pid_objname(pid) + scale = 90 / obj.dimensions.y + obj.scale = (scale, scale, scale) + bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Z'}) + bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN') + obj.location[0] = 0 + obj.location[1] = 0 + bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) - # 导入obj文件,重置到标准单位 - bpy.ops.wm.read_homefile() - bpy.context.preferences.view.language = 'en_US' - bpy.ops.object.delete(use_global=False, confirm=False) - bpy.context.scene.unit_settings.scale_length = 0.001 - bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' - bpy.context.scene.unit_settings.mass_unit = 'GRAMS' - - bpy.ops.import_scene.obj(filepath=filename) - #bpy.ops.wm.obj_import(filepath=filename) - obj = bpy.context.selected_objects[0] - bpy.context.view_layer.objects.active = obj - obj.select_set(True) - - pid_objname = find_pid_objname(pid) - - scale = 90 / obj.dimensions.y - obj.scale = (scale, scale, scale) - bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Z'}) - bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN') - obj.location[0] = 0 - obj.location[1] = 0 - bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) - - print(f'qr_position:{qr_position}') - print(f'qr_position_type:{type(qr_position)}') - - # 根据qr_position的值,恢复qr的位置和尺寸,重新生成贴图 - bpy.ops.object.load_reference_image(filepath=os.path.join(workdir, f'{pid}_{order_id}', 'qr.png')) - bpy.context.object.rotation_euler = (math.radians(-180), math.radians(0), qr_position['rotation']) - bpy.ops.transform.translate(value=qr_position['location'], orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False, snap=False, snap_elements={'INCREMENT'}, use_snap_project=False, snap_target='CLOSEST', use_snap_self=True, use_snap_edit=True, use_snap_nonedit=True, use_snap_selectable=False, release_confirm=True) - - bpy.context.object.empty_display_size = qr_position['dimensions'][0] - - qr_path = os.path.join(workdir,f'{pid}_{order_id}', f"{pid}_{order_id}Tex1_qr.png") - jpg_path = os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1.jpg") - #判断是否存在 jpg_path,不存在就执行下一个任务 - if not os.path.exists(jpg_path): - #移除该脚底板的面积处理 - res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') - os.system(f'blender -b -P fill_dm_code.py') - return - - jpg_img = Image.open(jpg_path) - shutil.copyfile(jpg_path, os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1_noqr.jpg")) - - bpy.context.scene.eyek.res_x = jpg_img.width - bpy.context.scene.eyek.res_y = jpg_img.height - bpy.context.scene.eyek.path_export_image = qr_path - bpy.data.objects[pid_objname].select_set(True) - bpy.data.objects['Empty'].select_set(True) - bpy.context.view_layer.objects.active = bpy.data.objects[pid_objname] - bpy.ops.eyek.exe() + print(f'qr_position:{qr_position}') + print(f'qr_position_type:{type(qr_position)}') + + # 根据qr_position的值,恢复qr的位置和尺寸,重新生成贴图 + bpy.ops.object.load_reference_image(filepath=os.path.join(workdir, f'{pid}_{order_id}', 'qr.png')) + bpy.context.object.rotation_euler = (math.radians(-180), math.radians(0), qr_position['rotation']) + bpy.ops.transform.translate(value=qr_position['location'], orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False, snap=False, snap_elements={'INCREMENT'}, use_snap_project=False, snap_target='CLOSEST', use_snap_self=True, use_snap_edit=True, use_snap_nonedit=True, use_snap_selectable=False, release_confirm=True) + + bpy.context.object.empty_display_size = qr_position['dimensions'][0] + + qr_path = os.path.join(workdir,f'{pid}_{order_id}', f"{pid}_{order_id}Tex1_qr.png") + jpg_path = os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1.jpg") + #判断是否存在 jpg_path,不存在就执行下一个任务 + if not os.path.exists(jpg_path): + #移除该脚底板的面积处理 + res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') + #os.system(f'blender -b -P fill_dm_code.py') + return - #判断qr_path是否存在,不存在就执行下一个任务 - if not os.path.exists(qr_path): - #移除该脚底板的面积处理 - res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') - os.system(f'blender -b -P fill_dm_code.py') - return + jpg_img = Image.open(jpg_path) + shutil.copyfile(jpg_path, os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1_noqr.jpg")) + + bpy.context.scene.eyek.res_x = jpg_img.width + bpy.context.scene.eyek.res_y = jpg_img.height + bpy.context.scene.eyek.path_export_image = qr_path + bpy.data.objects[pid_objname].select_set(True) + bpy.data.objects['Empty'].select_set(True) + bpy.context.view_layer.objects.active = bpy.data.objects[pid_objname] + bpy.ops.eyek.exe() + + #判断qr_path是否存在,不存在就执行下一个任务 + if not os.path.exists(qr_path): + #移除该脚底板的面积处理 + res = requests.get(f'https://mp.api.suwa3d.com/api/footCode/deleteByPid?pid={pid}') + #os.system(f'blender -b -P fill_dm_code.py') + return - qr_img = Image.open(qr_path) - jpg_img.paste(qr_img, (0, 0), qr_img) - jpg_img.save(jpg_path, quality=90) - shutil.copyfile(jpg_path, os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1_qr.jpg")) + qr_img = Image.open(qr_path) + jpg_img.paste(qr_img, (0, 0), qr_img) + jpg_img.save(jpg_path, quality=90) + shutil.copyfile(jpg_path, os.path.join(workdir,f'{pid}_{order_id}', f"{pid}Tex1_qr.jpg")) - # 加入去灰、锐化 - remove_gray_and_sharpening(jpg_path) + # 加入去灰、锐化 + remove_gray_and_sharpening(jpg_path) - #上传脚底板文件 -》 修改为移动脚底板文件 - upload_jpg_mtl(pid, order_id, print_id) + #上传脚底板文件 -》 修改为移动脚底板文件 + upload_jpg_mtl(pid, order_id, print_id) - # plt.axis('equal') - # plt.show() + # plt.axis('equal') + # plt.show() - # 保存blend文件 - # bpy.ops.wm.save_as_mainfile(filepath=f'{workdir}{pid}_{order_id}/{pid}_qr_end.blend') - bpy.ops.wm.quit_blender() + # 保存blend文件 + # bpy.ops.wm.save_as_mainfile(filepath=f'{workdir}{pid}_{order_id}/{pid}_qr_end.blend') + bpy.ops.wm.quit_blender() - # 删除临时文件 - print("workdirworkdir",workdir) - shutil.rmtree(os.path.join(workdir, f'{pid}_{order_id}')) - if only_one: - print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 运行{print_id}任务完成,退出程序') - break - else: - print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 运行{print_id}任务完成,继续运行下一个任务') - print_id = '0' - continue - - restart_current_process("blender -b -P fill_dm_code.py") + # 删除临时文件 + print("workdirworkdir",workdir) + shutil.rmtree(os.path.join(workdir, f'{pid}_{order_id}')) + if only_one: + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 运行{print_id}任务完成,退出程序') + break + else: + print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 运行{print_id}任务完成,继续运行下一个任务') + print_id = '0' + continue + + # restart_current_process("blender -b -P fill_dm_code.py") #根据print_id 获取 短网址 def get_short_url(print_id): @@ -681,8 +656,51 @@ def upload_jpg_mtl(pid, order_id, print_id): except Exception as e: print("迁移文件出 yichang ") + + +def worker(workdir, r, print_id): + """每个子进程的工作函数,用于处理单个 print_id。""" + try: + main(workdir, r, print_id) + except Exception as e: + print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f"处理 print_id {print_id} 时出错: {e}") + +def process_print_ids(workdir, r, pool_size): + """监控 Redis 队列并并行处理 print_id,同时控制进程池的大小。""" + # 创建进程池 + pool = multiprocessing.Pool(processes=pool_size) - + while True: + try: + # 如果队列为空,等待10秒后重试 + if r.llen('model:foot') == 0: + print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '队列为空,10秒后重试') + time.sleep(10) + continue + + # 从队列中取出一个 print_id + print_id = r.lpop('model:foot') + if print_id is None: + continue + + # 判断该 print_id 是否已经存在,避免重复处理 + isHaveAlready = 0 + for i in r.lrange('model:foot', 0, -1): + if i == print_id: + isHaveAlready = 1 + break + if isHaveAlready == 1: + continue + + # 如果 print_id 是唯一的,则将任务提交给进程池处理 + print(f"正在处理 print_id: {print_id}") + pool.apply_async(worker, args=(workdir, r, print_id)) # 使用 apply_async 异步执行任务 + + except Exception as e: + print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f"出现异常错误: {e}") + r = create_redis_connection() + continue + if __name__ == '__main__': atexit.register(common.notify,"打印工厂-本地虚拟木脚底板处理程序已停止一个") low_y_limit = 25000 @@ -714,17 +732,51 @@ if __name__ == '__main__': sourceFilePath = '/data/datasets/print' #脚底板最终保存的路径 resFilePath = '/data/datasets/complate/objs' - print("Usage: blender -b -P fill_dm_code.py") - + # 控制进程池的大小 + pool_size = 2 # 设置最大并发进程数为4(根据需求调整) + + # 创建一个进程池 + pool = multiprocessing.Pool(processes=pool_size) + + # 如果传递了参数,则处理特定的 print_ids if len(sys.argv) == 5: print_ids = sys.argv[-1] + for print_id in print_ids.split(','): + main(workdir, r, print_id) else: - print_ids = '0' - - print(f"print_ids--{print_ids}") - for print_id in print_ids.split(','): - main(workdir, r, print_id) - + # 启动进程池,监控队列并并行处理 print_id + process_print_ids(workdir, r, pool_size) + # if len(sys.argv) == 5: + # print_ids = sys.argv[-1] + # for print_id in print_ids.split(','): + # main(workdir, r, print_id) + # else: + # while True: + # try: + # #判断队列是否为空 + # if r.llen('model:foot') == 0: + # print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '队列为空,10秒后重试') + # time.sleep(10) + # continue + # #不为空,取出队列的第一个值 + # print_id = r.lpop('model:foot') + # if print_id is None: + # continue + # #判断是否存在相同的值 + # isHaveAlready = 0 + # for i in r.lrange('model:foot', 0, -1): + # if i == print_id: + # isHaveAlready = 1 + # break + # if isHaveAlready == 1: + # continue + # #如果是唯一值, 则调用main函数 + # main(workdir, r, print_id) + # except Exception as e: + # print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '出现异常错误,5秒后重试',e) + # r = create_redis_connection() + # continue +