Game Update 逻辑处理 - 整理中

本文介绍了一种在游戏中实现对象更新及交互检测的方法。通过将所有游戏对象放入同一个批节点中进行管理,并让每个对象遍历整个对象列表来检查是否与其他对象发生交互。此外,还详细介绍了PowerUps的具体实现方式,例如Mallet类的定义及其状态改变和位置更新的逻辑。

- 初始化时都加到一个batchNode中

3- 循环list中每一个object (这里定义了一个抽象类 GameCharacter,实现类有自己的实现方法)

    每个object都对list遍历一次,检测是否有交互。

#pragma mark –
#pragma mark Update Method
-(void) update:(ccTime)deltaTime {
	CCArray *listOfGameObjects = [sceneSpriteBatchNode children]; // 1
	for (GameCharacter *tempChar in listOfGameObjects) { // 2
     [tempChar updateStateWithDeltaTime:deltaTime 
            andListOfGameObjects: listOfGameObjects]; // 3
  }
}


- PowerUps 的实现:  GameObject 作为一个抽象类

//  Mallet.h
//  SpaceViking
//
#import <Foundation/Foundation.h>
#import "GameObject.h"

@interface Mallet : GameObject {
CCAnimation *malletAnim;
}
@property (nonatomic, retain) CCAnimation *malletAnim;
@end

//  Mallet.m
//  SpaceViking
//
#import "Mallet.h"
@implementation Mallet
@synthesize malletAnim;
- (void) dealloc {
    [malletAnim release];
    [super dealloc];
}
-(void)changeState:(CharacterStates)newState {
if (newState == kStateSpawning) {
id action = [CCRepeatForever actionWithAction:
                     [CCAnimate actionWithAnimation:malletAnim
restoreOriginalFrame:NO]];
        [self runAction:action];
    } else {
        [self setVisible:NO]; // Picked up
        [self removeFromParentAndCleanup:YES];
    }
}

-(void)updateStateWithDeltaTime:(ccTime)deltaTime
andListOfGameObjects:(CCArray*)listOfGameObjects {
float groundHeight = screenSize.height * 0.065f;
if ([self position].y > groundHeight) 
        [self setPosition:ccp([self position].x,
        [self position].y - 5.0f)];
}

-(void)initAnimations {
    [self setMalletAnim:
     [self loadPlistForAnimationWithName:@"malletAnim"
       andClassName:NSStringFromClass([self class])]];
}
-(id) init
{
if( (self=[super init]) )
    {
screenSize = [CCDirector sharedDirector].winSize;
gameObjectType = kPowerUpTypeMallet;
        [self initAnimations];
        [self changeState:kStateSpawning];
    }
return self;
}
@end




# !/usr/bin/env python3 # -*- coding: utf-8 -*- """ 说明:此文件是插件脚本的入口Py文件模板,任何其他插件脚本要加入Hubble,需以此模板为基础进行扩展开发 注意事项: 1. 插件文件命名和所在文件夹相同,例如DemoPlugin下面的DemoPlugin.py 2. 在HubblePlatform.py的trigger_plugin函数中,要更新配置变量plugin_property_dict(以后会放到线上去) 3. 新引入的Python3模块需要告知Hubble开发团队的后台部署人员 WX601464,pip3 install NewPackage.py后才能正常运行,否则会导致后台程序错误! 4. 任何问题请联系?WX601464/w30016103 """ import os import Hubble.utils.basic.HiviewLogger as HiviewLogger import re import datetime from datetime import datetime, timedelta import json class PluginClass(): """ Hubble程序会自动检测PluginClass名称的类,进行加工 1. self.logger: Hubble日志打印模块变量,可打印详细日志信息,便于后期调试,推荐使用self.logger.info("xxx"),本地调试时请注释self.logger相关命令。 2. self.plugin_result: Hubble能识别到的输出接口,最小填写量"conclusion""reason_info",具体解释请见变量定义处 3. plugin_preprocess: 预处理Hubble传入的info_dict,包含程序运行的基本信息 4. run_plugin_single: 单日志分析函数,插件脚本的分析能力体现于此 5. plugin_result_refinement: 对于批量处理多日志情况,run_plugin_single的单日志处理结果会汇总成一个结果列表, 基于此列表,用户可以进行二次精细化汇总,例如统计平均值等 """ def __init__(self): """ 初始化函数 """ self.logger = HiviewLogger.HiviewLogger().get_logger() self.plugin_result = { # 填好对应项,会在Hubble单任务分析报告里看见结果展示 "conclusion": { # 分析结论(定界结论)展示 "level_one": "", # 一级定界 "level_two": "", # 二级定界 "reason_info": "", # 根因信息 "solution": "", "weight_level": "" # 脚本权重,界面展示时作为排序依据,有效值范围[5,10] }, "analysis_process": { # 分析结论(定界过程)展示,列表中每一个dict元素代表定界过程中的一步 "show_order": [ # 展示顺序, 定义"1", "2", ...步骤 "1", "2" ], "detailed_process": { # 按show_order的步骤取出过程 "1": { "details": "", # 第一步详细信息(做了哪些处理总结下,例如在applogcat中找到Hubble关键字) "CN": "" # 步骤名称(例如找到applogcat文件) }, "2": { "details": "", # 第二步详细信息 "CN": "" # 步骤名称 } } }, "feature_data": { # 调用相似问题识别能力,需先填好此变量,可能有多个识别到的故障及其特征 "": [] # key值代表发现的故障类型,value值是list of string,由识别到的特征字符串组成 } } # 将'05-12 14:51:55'的时间格式转换成时间2024-05-12 14:51:55 def log_str_to_datetime(self, time_str): issue_time = datetime.strptime(time_str, '%m-%d %H:%M:%S') current_year = datetime.now().year issue_time_with_current_year = issue_time.replace(year=current_year) return issue_time_with_current_year def extract_datetime(self, string): pattern = r"_(\d{8})_(\d{4})" match = re.search(pattern, string) if match: return match.group(1) + "_" + match.group(2) else: return None # 1低内存 def memAvailable(self, event_arr): for line in event_arr: monsc_re = re.compile('MemAvailable:(.*)kB Buffers').search(line) if monsc_re: monsc_tuples = monsc_re.groups() memAvailable_vale = monsc_tuples[0] if int(memAvailable_vale) < 1048576: return 1 return 0 # 2杀后台 def am_kill(self, event_arr): for line in event_arr: if ('I am_kill' in line) or ('ActivityManager: Process' in line) or ('lowmemorykiller: Killing' in line): return 1 return 0 # 3网络不佳 def rtt_rate(self, app_arr): rtt_num = 0 for line in app_arr: rtt_re = re.compile('PTcp RTT:(.*), rtt').search(line) if rtt_re: rtt_tuples = rtt_re.groups() rtt_value = rtt_tuples[0] if int(rtt_value) > 800: rtt_num += 1 if rtt_num >= 2: return 1 return 0 # 4前台应用丢帧 def choreographer(self, app_arr): for line in app_arr: if 'Choreographer: Skipped' in line: return 1 return 0 # 5热限频 def temperature(self, app_arr): target_frame = '' for line in app_arr: frame_re = re.compile('shell_frame] tempNew :(.*) tempOld').search(line) if frame_re: frame_tuples = frame_re.groups() frame_value = frame_tuples[0] if int(frame_value) > 43: return 1 return 0 # 6低电限频 def cluster_freq(self, app_arr): for line in app_arr: if 'hisi_vbat_drop_cluster_freq_set' in line: return 1 return 0 # 7编译优化 def compiler_optimization(self, app_arr): for line in app_arr: if 'Failed execv(/system/bin/dex2oat' in line: return 1 return 0 # 8IO阻塞 def blockage(self, kernel_arr): for line in kernel_arr: if '[BLK-IO]io_latency' in line: return 1 return 0 # 9整机碎片化过高 def free_sec(self, kernel_arr): for line in kernel_arr: free_sec_re = re.compile('free_sec=(.*),reserved_sec').search(line) free_re = re.compile(',Free=(.*)MB,count=').search(line) if free_sec_re and free_re: free_sec_tuples = free_sec_re.groups() free_sec_value = free_sec_tuples[0] free_tuples = free_re.groups() free_value = free_tuples[0] res_value = 1 - (int(free_sec_value) * 2) / int(free_value) if res_value > 0.8: return 1 return 0 # 10应用卡死、无响应 def am_anr(self, event_arr): for line in event_arr: if 'am_anr' in line: return 1 return 0 # 11冻屏\黑屏 def timeout_function(self, xcolie_arr): for line in xcolie_arr: if 'timeout function' in line: return 1 return 0 # 12binder资源不足 def binder_loss(self, kernel_arr): for line in kernel_arr: if 'no async space left' in line: return 1 return 0 # 13后台GC阻塞前台 def wait_for_gc(self, app_arr): for line in app_arr: if 'WaitForGcToComplete' in line: return 1 return 0 # 14高温限帧 def over_heat_lcd_fps(self, app_arr): for line in app_arr: fps_re_mate = re.compile('overHeatLcdFps (.*), multiMaxLcdFreq').search(line) if fps_re_mate: fps_tuples_mate = fps_re_mate.groups() fps_vale_mate = fps_tuples_mate[0] if int(fps_vale_mate) != -1: return 1 else: fps_re = re.compile('overHeatLcdFps (.*), final refresh').search(line) if fps_re: self.logger.info('chenshuang:') fps_tuples = fps_re.groups() self.logger.info(fps_tuples) fps_vale = fps_tuples[0] if int(fps_vale) != -1: return 1 return 0 # 17应用启动完成时延 def activity_task_manager(self, app_arr): for line in app_arr: display_re = re.compile('ActivityTaskManager: Displayed (.*)ms').search(line) if display_re: display_tuples = display_re.groups() display_value = display_tuples[0] display_time = display_value.split('+')[-1] display_trans = display_time.split('s') if len(display_trans) > 1: display_res = int(display_trans[0]) * 1000 + int(display_trans[1]) print(display_res) else: display_res = int(display_trans[0]) if display_res > 1500: return 1 return 0 # 19 input事件无响应 def inputDispatcher(self, app_arr): for line in app_arr: if 'InputDispatcher: Dropping' in line: return 1 return 0 # 20 亮屏解锁慢 def unlock_slow(self, app_arr): for line in app_arr: if 'Keyguard drawn timeout' in line or 'Timeout waiting for drawn' in line: return 1 return 0 # 21 音频播放卡顿 def audio_slow(self, app_arr): for line in app_arr: if 'E AudioFlinger: writing blocked, write to hal costs:' in line: return 1 return 0 # 22 游戏卡顿 def game_slow(self, app_arr): # 只检测游戏0和游戏4,为了不改动代码,所以直接降其他游戏检测项置零 res = [0, 0, 0, 0, 0, 0, 0, 0] for line in app_arr: game_re = re.compile('gamesdk update status: (.*)').search(line) if game_re: game_tuples = game_re.groups() game_vale = game_tuples[0] dict_game = json.loads(game_vale[1:-1]) if ("pkg" in dict_game) and ("4" in dict_game) and ("12" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["12"] > 150): res[0] = 1 if ("pkg" in dict_game) and ("4" in dict_game) and ("5" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 75) and ( (dict_game["7"] == 90) or (dict_game["7"] == 120) or (dict_game["7"] == 144)): res[1] = 0 if ("pkg" in dict_game) and ("4" in dict_game) and ("5" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 50) and ( dict_game["7"] == 60): res[2] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 25) and ( dict_game["7"] == 30): res[3] = 0 if ("pkg" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["7"] > 150): res[4] = 1 if ("pkg" in dict_game) and ("10" in dict_game) and ("3" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and (dict_game["10"] == 30) and ( dict_game["3"] < 25): res[5] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and (dict_game["10"] == 60) and ( dict_game["3"] < 50): res[6] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and ( (dict_game["10"] == 90) or (dict_game["10"] == 120) or (dict_game["10"] == 144)) and ( dict_game["3"] < 75): res[7] = 0 return res # jank日志解析 --存储不足,整机lowait,限频,省电模式,高负载,低内存 def jank_log(self, jank_arr): res = [0, 0, 0, 0, 0, 0] for line in jank_arr: freed_re = re.compile('FreeDisk":(.*),').search(line) io_re = re.compile('Iowait":(.*),').search(line) limit_re = re.compile('Limit_Freq":(.*),').search(line) power_re = re.compile('bPowerSavingOn":(.*),').search(line) cpu_re = re.compile('CpuLoad":(.*),').search(line) available_re = re.compile('AvailableMem":(.*),').search(line) if freed_re: freed_tuples = freed_re.groups() freed_value = freed_tuples[0] if int(freed_value) < 15360: res[0] = 1 if io_re: io_tuples = io_re.groups() io_value = io_tuples[0] if int(io_value) > 80: res[1] = 1 if limit_re: limit_tuples = limit_re.groups() limit_value = limit_tuples[0] if int(limit_value) == 1: res[2] = 0 if power_re: power_tuples = power_re.groups() power_value = power_tuples[0] if (int(power_value) == 1) or (int(power_value) == 4): res[3] = 1 if cpu_re: cpu_tuples = cpu_re.groups() cpu_value = cpu_tuples[0] if int(cpu_value) > 6000: res[4] = 1 if available_re: available_tuples = available_re.groups() available_value = available_tuples[0] if int(available_value) < 819200: res[5] = 1 return res def plugin_preprocess(self, info_dict=None): """ 预处理Hubble传入的info_dict,包含程序运行的基本信息 此函数的基础操作是获取下载日志列表地址,形成task_list任务分析列表,供Hubble调用 """ self.logger.info("这是预处理函数?") task_list = [] download_list = info_dict["common_info"]["log_download_list"] max_analysis_num = 1 # 最多处理几个日志 if len(download_list) > max_analysis_num: download_list = download_list[:max_analysis_num] for download_item in download_list: task_dict = {"download_addr": [], "task_params": {}} task_dict["download_addr"] = download_item task_list.append(task_dict) return task_list def run_plugin_single(self, uuid_log_path=None, log_path=None, param_dict=None): """ 主脚本分析逻辑,分析单日志中存在的故障,存入self.plugin_result 1. uuid_log_path: Hubble单任务的顶级分析路径,包含生成的基本信息文件、结果文件和递归解压的日志文件夹 2. log_path: 递归解压的顶级日志文件夹,一般是uuid_log_path的子文件 3. param_dict: 脚本程序所需的参数信息,例如日志来源、领域等, --------------------------------------------------- 参数示例 BetaClub的param_dict示例: param_dict = {"common_info":{'happen_time': '20230225182000', 'betano': '2103539765', 'version': 'FCO-AL00 3.1.0.115(SP2C00E110R2P3log)', 'product': 'FCO-AL00', 'logsource': 'BetaClub', 'beta_info': {'quesDetail': '图库退出卡顿。', 'faultNameLv1': '性能', 'faultNameLv2': '整机操作各种卡', 'activityName': '【旗舰手机PDU】【关键】FCO-AL00 Beta测试', 'faultCode': '1008_1002'}, 'happen_time_unixtime': 1677320400000, 'label': '动效卡顿', 'l_pkgs': ['com.huawei.photos']}} APR的param_dict示例: param_dict = {'common_info': {'version': 'MNA-AL00 3.1.0.125(SP1DEMC735E126R2P2)', 'eventid': '901001002','errorcode2': '', 'errorcode4': '', 'logsource': 'AresOcean', 'errorcode3': '', 'product': 'MNA-AL00', 'datetime_str': '20230327112414'}} 建议通过字典的get方法进行取值,如可通过下述语句获取用户描述和产品名称: brief = param_dict.get("common_info", {}).get("beta_info", {}).get("quesDetail", "") product = param_dict.get("common_info", {}).get("product", "") """ self.logger.info("这是测试插件!uuid_log_path=[%s], log_path=[%s], param_dict=[%s]", uuid_log_path, log_path, param_dict) # 此句为DemoPlugin.py独有,可删除 # 此代码块为文件路径的遍历方法,以hiapplogcat-log为例 app_path = [] screenshot = [] screenvideo = [] event_path = [] kernel_path = [] jankexec_path = [] for root, dirs, files in os.walk(uuid_log_path): for file in files: if "hiapplogcat-log" in file: # 可替换为其它日志类型 app_path.append(os.path.join(root, file)) if "Screenshot" in file: screenshot.append(os.path.join(root, file)) if "SVID_" in file: screenvideo.append(os.path.join(root, file)) if "eventslogcat-log" in file: event_path.append(os.path.join(root, file)) if "kmsgcat-log" in file: kernel_path.append(os.path.join(root, file)) if "jankexec.log" in file: jankexec_path.append(os.path.join(root, file)) # 对app,event,kernel日志按照时间顺序进行排序 event_path = sorted(event_path, key=lambda f: f[-34:]) app_path = sorted(app_path, key=lambda g: g[-34:]) kernel_path = sorted(kernel_path, key=lambda g: g[-34:]) level_one = "稳定与流畅" # 临时二级定界字符串 conclusion = '详情请看根因分析' # 打开app日志 app_list = [] for app in app_path: with open(app, "r", encoding="utf-8", errors='ignore') as app_reader: app_line = app_reader.readlines() app_list += app_line app_time_end = app_list[-1] if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', app_time_end[:14]): app_end = app_time_end[:14] else: app_time_end = app_list[-10] app_end = app_time_end[:14] app_arr = [] if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', app_end): app_end_time = self.log_str_to_datetime(app_end) for app_key in app_list: if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', app_key[:14]): app_key_time = self.log_str_to_datetime(app_key[:14]) if app_key_time > app_end_time - timedelta(minutes=10): app_arr.append(app_key) else: app_arr = app_list # 打开event日志 event_list = [] for event in event_path: with open(event, "r", encoding="utf-8", errors='ignore') as event_reader: event_line = event_reader.readlines() event_list += event_line event_time_end = event_list[-1] if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', event_time_end[:14]): event_end = event_time_end[:14] else: event_time_end = event_list[-2] event_end = event_time_end[:14] event_arr = [] event_end_time = self.log_str_to_datetime(event_end) for event_key in event_list: if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', event_key[:14]): event_key_time = self.log_str_to_datetime(event_key[:14]) if event_key_time > event_end_time - timedelta(minutes=10): event_arr.append(event_key) # 打开kernel日志 kernel_list = [] for kernel in kernel_path: with open(kernel, "r", encoding="utf-8", errors='ignore') as kernel_reader: kernel_line = kernel_reader.readlines() kernel_list += kernel_line kernel_time_end = kernel_list[-1] if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', kernel_time_end[:14]): kernel_end = kernel_time_end[:14] else: kernel_time_end = kernel_list[-2] kernel_end = kernel_time_end[:14] kernel_arr = [] kernel_end_time = self.log_str_to_datetime(kernel_end) for kernel_key in kernel_list: if re.match(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', kernel_key[:14]): kernel_key_time = self.log_str_to_datetime(kernel_key[:14]) if kernel_key_time > kernel_end_time - timedelta(minutes=10): kernel_arr.append(kernel_key) # 打开jankexec日志 jankexec_list = [] for jankexec in jankexec_path: with open(jankexec, "r", encoding="utf-8", errors='ignore') as jankexec_reader: jankexec_line = jankexec_reader.readlines() jankexec_list += jankexec_line first = self.memAvailable(event_arr) # 1低内存 second = self.am_kill(event_arr) # 2杀后台 third = self.rtt_rate(app_arr) # 3网络不佳 fourth = self.choreographer(app_arr) # 4前台应用丢帧 fifth = self.temperature(app_arr) # 5热限频 sixth = self.cluster_freq(app_arr) # 6低电限频 seventh = self.compiler_optimization(app_arr) # 7编译优化 eighth = self.blockage(kernel_arr) # 8IO阻塞 ninth = self.free_sec(kernel_arr) # 9整机碎片化过高 tenth = self.am_anr(event_arr) # 10应用卡死、无响应 twelfth = self.binder_loss(kernel_arr) # 12binder资源不足 thirteenth = self.wait_for_gc(app_arr) # 13后台GC阻塞前台 fourteenth = self.over_heat_lcd_fps(app_arr) # 14高温限帧 seventeenth = self.activity_task_manager(app_arr) # 17应用启动完成时延 nineteenth = self.inputDispatcher(app_arr) # 19 input事件无响应 twentieth = self.unlock_slow(app_arr) # 20 亮屏解锁慢 twen_one = self.audio_slow(app_arr) # 21 音频播放卡顿 twen_two = self.game_slow(app_arr) # 22 游戏卡顿 jank_res = self.jank_log(jankexec_list) res = [first, second, third, fourth, 0, sixth, seventh, eighth, ninth, tenth, 0, twelfth, thirteenth, fourteenth, 0, 0, 0, 0, nineteenth, 0, 0] + twen_two + jank_res self.logger.info(res) res_str = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] res_str[0] = ['整机低内存', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] res_str[1] = ['后台应用被清理查杀', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] res_str[2] = ['网络不佳', '调整到网络环境状态良好WIFI或移动数据下再体验'] res_str[3] = ['', ''] res_str[4] = ['高温限频', '建议尽量避免边充电边使用,适当降低屏幕亮度,关闭不使用或异常耗电的应用与功能开关(如:热点、“蓝牙”、NFC' '等);游戏时适当降低画质,帧率和分辨率设置,可提升使用体验,减少发热;降低外放音量能降低扬声器功耗,或使用耳机播放声音可以有效减少发热;熄屏待设备降温后再查看使用。'] res_str[5] = ['低电欠压限频', '手机/平板低电量(<20%)的时候,低电量模式,手机或平板会降低性能以节省电量,保障续航,建议将设备电量保持在20%以上下使用体验。'] res_str[6] = ['应用刚更新补丁或者大版本时需要一定周期内做代码的编译优化', '建议将设备灭屏充电4小时以上(最好能灭屏充电一晚上),重启设备以保证系统及已安装的应用已进行优化,三天后可以再观察使用;'] res_str[7] = ['数据读写阻塞', '建议引导用户进入手机管家针对存储空间进行清理优化,并在夜间保持充电习惯,建议将设备灭屏充电4小时以上(最好能灭屏充电一晚上),重启设备促进系统的碎片文件整理'] res_str[8] = ['整机碎片化过高', '建议引导用户进入手机管家针对存储空间进行清理优化,并在夜间保持充电习惯,建议将设备灭屏充电4小时以上(最好能灭屏充电一晚上),重启设备促进系统的碎片文件整理'] res_str[9] = ['应用卡死、无响应', '建议重启应用或设备后再体验,同时前往应用市场检测更新应用版本'] res_str[10] = ['', ''] res_str[11] = ['binder资源不足(进程调用资源不足)', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] res_str[12] = ['后台GC阻塞前台(应用自身运行时占用内存过高,自己触发垃圾回收,可能阻塞前台业务;整机负载高)', '清理应用缓存并重启应用后尝试;建议备份数据卸载重装应用尝试;引导用户反馈三方渠道排查或等待应用版本更新'] res_str[13] = ['高温限帧', '建议尽量避免边充电边使用,适当降低屏幕亮度,关闭不使用或异常耗电的应用与功能开关(如:热点、“蓝牙”、NFC等);游戏时适当降低画质,帧率和分辨率设置,可提升使用体验,减少发热;降低外放音量能降低扬声器功耗,或使用耳机播放声音可以有效减少发热;熄屏待设备降温后再查看使用。'] res_str[14] = ['', ''] res_str[15] = ['', ''] res_str[16] = ['', ''] res_str[17] = ['', ''] res_str[18] = ['应用响应超时(自身前台业务复杂或触控操作过于高频,导致应用自身响应触控操作不及时)', '建议重启应用或设备后再体验,同时前往应用市场检测更新应用版本'] res_str[19] = ['', ''] res_str[20] = ['', ''] res_str[21] = ['王者荣耀对局中网络差', '调整到网络环境状态良好WIFI或移动数据下再体验'] res_str[25] = ['和平精英游戏网络时延高(实时网络时高于150ms)', '调整到网络环境状态良好WIFI或移动数据下再体验'] res_str[29] = ['整机存储不足', '建议引导清理设备存储空间,清理不常用的应用和文件,将手机存储空间预留20%及以上,保持充足的存储空间。'] res_str[30] = ['整机IO阻塞过多(数据读写阻塞)', '建议引导用户进入手机管家针对存储空间进行清理优化,并在夜间保持充电习惯,建议将设备灭屏充电4小时以上(最好能灭屏充电一晚上),重启设备促进系统的碎片文件整理'] res_str[32] = ['处于省电模式', '建议关闭(设置 > 电池 > 省电模式和 超级省电),并保持电量充足(20%以上)。省电模式和低电量情况下,设备会降低性能以节省电量。'] res_str[33] = ['整机高负载', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] res_str[34] = ['整机低内存', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] conclusion_res = [] solution_res = [] for i, key in enumerate(res): if key: conclusion_res.append(res_str[i][0]) solution_res.append(res_str[i][1]) if not conclusion_res: self.plugin_result["conclusion"]['level_one'] = level_one # 一级定界,反映插件功能 self.plugin_result["conclusion"]['level_two'] = '整机卡顿' # 二级定界,根据插件得到的不同结论进行调整 self.plugin_result["conclusion"]['reason_info'] = '当前整机各项指标未诊断出异常' # 二级定界,根据插件得到的不同结论进行调整 self.plugin_result["conclusion"]['solution'] = '建议引导用户重新复现问题反馈日志' # 二级定界,根据插件得到的不同结论进行调整 return self.plugin_result # 如果想直接利用Hubble前端分析报告的展示项,请按定义填写好self.plugin_result变量 con_res = '' solu_res = '' for j, key_solution in enumerate(conclusion_res): if key_solution in con_res: continue else: con_res += '<br>' + '发现异常:' + key_solution + '<br>' tmp = 0 for p, key in enumerate(solution_res): if key in solu_res: continue else: tmp += 1 solu_res += '<br>' + str(tmp) + ' : ' + key + '<br>' # 此代码块用于结论赋值,未找到有效结论时不赋值即可 if conclusion: self.plugin_result["conclusion"]['level_one'] = level_one # 一级定界,反映插件功能 self.plugin_result["conclusion"]['level_two'] = '整机卡顿' # 二级定界,根据插件得到的不同结论进行调整 self.plugin_result["conclusion"]['reason_info'] = con_res # 二级定界,根据插件得到的不同结论进行调整 self.plugin_result["conclusion"]['solution'] = solu_res # 二级定界,根据插件得到的不同结论进行调整 self.logger.info(self.plugin_result) return self.plugin_result # 如果想直接利用Hubble前端分析报告的展示项,请按定义填写好self.plugin_result变量 def plugin_result_refinement(self, result_list=None): """ 二次精细化加工产生的此脚本分析结果列表? result_list中是self.plugin_result元素的列表集合 也即result_list = [self.plugin_result_1, self.plugin_result_2,...] """ self.logger.info("这是分析结果精加工函数") return result_list # 如果是此分析脚本定制化的分析结果数据结构,需要和Hubble对齐前端取数逻辑才能将分析结论显示在分析报告内 这份脚本挺好的,内容不用怎么改,注释不要给我删了,帮我加一个判断,然后返回一份完整的代码给我: 是否开启免打扰 “DO_NOT_DISTURB、suppressed by DND、suppressed due to DND、isZenmodOn :true、zenmode_notification_tag” NotificationEntryMgr: No peeking: suppressed by DND: 0|com.android.mms|54|null|10043 hilogs\hiapplogcat 关键字命中 开启了免打扰 建议关闭免打扰
09-27
<think>根据需求,我们需要在现有的插件中添加一个判断:检测日志中是否开启了免打扰模式(DND)。具体来说,我们需要在日志中搜索以下关键字: "DO_NOT_DISTURB", "suppressed by DND", "suppressed due to DND", "isZenmodOn :true", "zenmode_notification_tag" 计划步骤: 1. 在`run_plugin_single`函数中,我们在读取applogcat日志后,增加一个检测免打扰模式的函数调用。 2. 编写一个函数`check_do_not_disturb`,用于在日志行中检测上述关键字。 3. 将检测结果整合到现有的结论数组中,并添加对应的结论描述和解决方案。 注意:现有的结论数组`res`是一个包含多个检测结果的列表,我们需要在适当的位置加入免打扰的检测结果(比如在数组末尾新增一个位置)。 但是考虑到现有数组已经固定了35个位置(0-34),我们可以将免打扰的检测结果放在一个新的位置(比如索引35)。但是这样需要调整`res_str`数组的大小和内容。 然而,为了避免破坏原有的索引结构,我们可以考虑在数组的末尾添加一个新的元素(即第35个元素,索引35)。同时,需要扩展`res_str`数组,使其包含索引35的项。 具体修改如下: 1. 在`run_plugin_single`函数中,读取`app_arr`后,调用`check_do_not_disturb`函数(我们新增的函数)检测免打扰关键字。 2. 将检测结果(0或1)添加到`res`列表的末尾(即索引35的位置)。 3. 在`res_str`数组中,添加索引35的项,包括结论描述和解决方案。 但是,观察现有代码,`res`和`res_str`的长度都是固定的。目前`res`有35个元素(0-34),而`res_str`有36个元素(0-35)。但是`res_str`的索引35并没有被使用(因为`res`的长度为35,最大索引34)。因此,我们可以在`res`增加一个元素(索引35),并在`res_str`的索引35位置添加免打扰的结论和解决方案。 修改步骤: 1. 在`res`列表后面追加免打扰的检测结果:`res.append(self.check_do_not_disturb(app_arr))` 2. 在`res_str`数组中,为索引35添加内容:`res_str[35] = ['开启了免打扰', '建议关闭免打扰']` 另外,我们需要定义`check_do_not_disturb`函数,用于检测免打扰关键字。 注意:由于日志量可能很大,我们只需遍历一次日志数组,一旦发现任何一个关键字,即可返回1(表示开启免打扰),否则返回0。 代码实现: 在`PluginClass`中添加以下函数: ```python # 检测免打扰模式 def check_do_not_disturb(self, app_arr): dnd_keywords = [ "DO_NOT_DISTURB", "suppressed by DND", "suppressed due to DND", "isZenmodOn :true", "zenmode_notification_tag" ] for line in app_arr: for keyword in dnd_keywords: if keyword in line: return 1 return 0 ``` 在`run_plugin_single`函数中,在计算`res`数组之后,添加免打扰的检测: ```python # ... 原有的res计算 # 35: 是否开启免打扰 thirty_fifth = self.check_do_not_disturb(app_arr) res.append(thirty_fifth) # ... 后续的res_str定义 ``` 同时,在`res_str`数组中,添加索引35的项(注意原数组长度为36,索引35已有但可能是空,我们覆盖它): ```python res_str = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] # ... 其他赋值 res_str[35] = ['开启了免打扰', '建议关闭免打扰'] ``` 但是注意,原有的`res_str`数组在创建时是36个空列表(索引0到35),而我们之前只给0到34赋值了,35是空的。所以我们现在只需要给35赋值即可。 另外,在后续的遍历中,我们只处理非空的结论,所以不会影响。 最后,在遍历`res`数组生成结论时,新增的索引35也会被处理。 注意:由于我们新增了一个检测项,所以`res`数组的长度变为36,而`res_str`数组的长度也是36(0-35),所以不会越界。 完整修改后的代码(只显示修改部分)如下: 1. 在类中添加`check_do_not_disturb`函数。 2. 在`run_plugin_single`函数中,在计算完所有原有的检测后,添加免打扰检测,并追加到`res`列表。 3. 在`res_str`数组中,为索引35赋值。 注意:为了避免重复,我们使用一个单独的索引位置(35)来存储免打扰的检测结果。 由于代码较长,我们只提供修改部分的代码,并将完整代码粘贴在最后(包含注释)。 注意:由于原有代码中`res_str`数组在创建时有36个元素(0-35),所以我们不需要改变其长度,只需要给索引35赋值。 修改后的`run_plugin_single`函数中相关代码: ```python # ... 前面的代码不变 # 22 游戏卡顿 twen_two = self.game_slow(app_arr) jank_res = self.jank_log(jankexec_list) res = [first, second, third, fourth, 0, sixth, seventh, eighth, ninth, tenth, 0, twelfth, thirteenth, fourteenth, 0, 0, 0, 0, nineteenth, 0, 0] + twen_two + jank_res # 新增免打扰检测(第35项) dnd_detected = self.check_do_not_disturb(app_arr) res.append(dnd_detected) # 索引35 self.logger.info(res) res_str = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] # 注意这里创建了36个空列表(0-35) res_str[0] = ['整机低内存', '清除后台应用:桌面手势导航底部上划进入多任务中心,清理后台多任务应用卡片(三键导航点击导航键的方块图标可以进入多任务界面),定期(2-3天)关机重启设备。<br>进入手机管家进行深度清理存储空间,并在设置-应用管理中关闭不常用应用的自启应用、关联启动、后台活动'] # ... 其他res_str赋值(略) res_str[35] = ['开启了免打扰', '建议关闭免打扰'] # ... 后续代码不变 ``` 注意:在`res_str`数组中,我们给索引35赋值为免打扰的结论和解决方案。 最后,我们提供完整的`PluginClass`代码(由于代码过长,只显示修改后的关键部分,但保证完整可运行)。 注意:由于代码很长,我们只修改了必要部分,其他部分保持不变。 </think>我将为你添加免打扰模式的检测功能到现有脚本中。以下是完整的修改后代码: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 说明:此文件是插件脚本的入口Py文件模板,任何其他插件脚本要加入Hubble,需以此模板为基础进行扩展开发 注意事项: 1. 插件文件命名和所在文件夹相同,例如DemoPlugin下面的DemoPlugin.py 2. 在HubblePlatform.py的trigger_plugin函数中,要更新配置变量plugin_property_dict(以后会放到线上去) 3. 新引入的Python3模块需要告知Hubble开发团队的后台部署人员 WX601464,pip3 install NewPackage.py后才能正常运行,否则会导致后台程序错误! 4. 任何问题请联系?WX601464/w30016103 """ import os import Hubble.utils.basic.HiviewLogger as HiviewLogger import re import datetime from datetime import datetime, timedelta import json class PluginClass(): """ Hubble程序会自动检测PluginClass名称的类,进行加工 1. self.logger: Hubble日志打印模块变量,可打印详细日志信息,便于后期调试,推荐使用self.logger.info("xxx"),本地调试时请注释self.logger相关命令。 2. self.plugin_result: Hubble能识别到的输出接口,最小填写量"conclusion""reason_info",具体解释请见变量定义处 3. plugin_preprocess: 预处理Hubble传入的info_dict,包含程序运行的基本信息 4. run_plugin_single: 单日志分析函数,插件脚本的分析能力体现于此 5. plugin_result_refinement: 对于批量处理多日志情况,run_plugin_single的单日志处理结果会汇总成一个结果列表, 基于此列表,用户可以进行二次精细化汇总,例如统计平均值等 """ def __init__(self): """ 初始化函数 """ self.logger = HiviewLogger.HiviewLogger().get_logger() self.plugin_result = { # 填好对应项,会在Hubble单任务分析报告里看见结果展示 "conclusion": { # 分析结论(定界结论)展示 "level_one": "", # 一级定界 "level_two": "", # 二级定界 "reason_info": "", # 根因信息 "solution": "", "weight_level": "" # 脚本权重,界面展示时作为排序依据,有效值范围[5,10] }, "analysis_process": { # 分析结论(定界过程)展示,列表中每一个dict元素代表定界过程中的一步 "show_order": [ # 展示顺序, 定义"1", "2", ...步骤 "1", "2" ], "detailed_process": { # 按show_order的步骤取出过程 "1": { "details": "", # 第一步详细信息(做了哪些处理总结下,例如在applogcat中找到Hubble关键字) "CN": "" # 步骤名称(例如找到applogcat文件) }, "2": { "details": "", # 第二步详细信息 "CN": "" # 步骤名称 } } }, "feature_data": { # 调用相似问题识别能力,需先填好此变量,可能有多个识别到的故障及其特征 "": [] # key值代表发现的故障类型,value值是list of string,由识别到的特征字符串组成 } } # 将'05-12 14:51:55'的时间格式转换成时间2024-05-12 14:51:55 def log_str_to_datetime(self, time_str): issue_time = datetime.strptime(time_str, '%m-%d %H:%M:%S') current_year = datetime.now().year issue_time_with_current_year = issue_time.replace(year=current_year) return issue_time_with_current_year def extract_datetime(self, string): pattern = r"_(\d{8})_(\d{4})" match = re.search(pattern, string) if match: return match.group(1) + "_" + match.group(2) else: return None # 检测免打扰模式 def check_do_not_disturb(self, app_arr): """ 检测是否开启了免打扰模式 关键字列表: - "DO_NOT_DISTURB" - "suppressed by DND" - "suppressed due to DND" - "isZenmodOn :true" - "zenmode_notification_tag" - "NotificationEntryMgr:" """ dnd_keywords = [ "DO_NOT_DISTURB", "suppressed by DND", "suppressed due to DND", "isZenmodOn :true", "zenmode_notification_tag", "NotificationEntryMgr:", "suppressed by DND", "No peeking: suppressed by DND" ] # 编译正则表达式,匹配关键字(不区分大小写) dnd_pattern = re.compile("|".join(dnd_keywords), re.IGNORECASE) for line in app_arr: if dnd_pattern.search(line): return 1 return 0 # 1低内存 def memAvailable(self, event_arr): for line in event_arr: monsc_re = re.compile('MemAvailable:(.*)kB Buffers').search(line) if monsc_re: monsc_tuples = monsc_re.groups() memAvailable_vale = monsc_tuples[0] if int(memAvailable_vale) < 1048576: return 1 return 0 # 2杀后台 def am_kill(self, event_arr): for line in event_arr: if ('I am_kill' in line) or ('ActivityManager: Process' in line) or ('lowmemorykiller: Killing' in line): return 1 return 0 # 3网络不佳 def rtt_rate(self, app_arr): rtt_num = 0 for line in app_arr: rtt_re = re.compile('PTcp RTT:(.*), rtt').search(line) if rtt_re: rtt_tuples = rtt_re.groups() rtt_value = rtt_tuples[0] if int(rtt_value) > 800: rtt_num += 1 if rtt_num >= 2: return 1 return 0 # 4前台应用丢帧 def choreographer(self, app_arr): for line in app_arr: if 'Choreographer: Skipped' in line: return 1 return 0 # 5热限频 def temperature(self, app_arr): target_frame = '' for line in app_arr: frame_re = re.compile('shell_frame] tempNew :(.*) tempOld').search(line) if frame_re: frame_tuples = frame_re.groups() frame_value = frame_tuples[0] if int(frame_value) > 43: return 1 return 0 # 6低电限频 def cluster_freq(self, app_arr): for line in app_arr: if 'hisi_vbat_drop_cluster_freq_set' in line: return 1 return 0 # 7编译优化 def compiler_optimization(self, app_arr): for line in app_arr: if 'Failed execv(/system/bin/dex2oat' in line: return 1 return 0 # 8IO阻塞 def blockage(self, kernel_arr): for line in kernel_arr: if '[BLK-IO]io_latency' in line: return 1 return 0 # 9整机碎片化过高 def free_sec(self, kernel_arr): for line in kernel_arr: free_sec_re = re.compile('free_sec=(.*),reserved_sec').search(line) free_re = re.compile(',Free=(.*)MB,count=').search(line) if free_sec_re and free_re: free_sec_tuples = free_sec_re.groups() free_sec_value = free_sec_tuples[0] free_tuples = free_re.groups() free_value = free_tuples[0] res_value = 1 - (int(free_sec_value) * 2) / int(free_value) if res_value > 0.8: return 1 return 0 # 10应用卡死、无响应 def am_anr(self, event_arr): for line in event_arr: if 'am_anr' in line: return 1 return 0 # 11冻屏\黑屏 def timeout_function(self, xcolie_arr): for line in xcolie_arr: if 'timeout function' in line: return 1 return 0 # 12binder资源不足 def binder_loss(self, kernel_arr): for line in kernel_arr: if 'no async space left' in line: return 1 return 0 # 13后台GC阻塞前台 def wait_for_gc(self, app_arr): for line in app_arr: if 'WaitForGcToComplete' in line: return 1 return 0 # 14高温限帧 def over_heat_lcd_fps(self, app_arr): for line in app_arr: fps_re_mate = re.compile('overHeatLcdFps (.*), multiMaxLcdFreq').search(line) if fps_re_mate: fps_tuples_mate = fps_re_mate.groups() fps_vale_mate = fps_tuples_mate[0] if int(fps_vale_mate) != -1: return 1 else: fps_re = re.compile('overHeatLcdFps (.*), final refresh').search(line) if fps_re: self.logger.info('chenshuang:') fps_tuples = fps_re.groups() self.logger.info(fps_tuples) fps_vale = fps_tuples[0] if int(fps_vale) != -1: return 1 return 0 # 17应用启动完成时延 def activity_task_manager(self, app_arr): for line in app_arr: display_re = re.compile('ActivityTaskManager: Displayed (.*)ms').search(line) if display_re: display_tuples = display_re.groups() display_value = display_tuples[0] display_time = display_value.split('+')[-1] display_trans = display_time.split('s') if len(display_trans) > 1: display_res = int(display_trans[0]) * 1000 + int(display_trans[1]) print(display_res) else: display_res = int(display_trans[0]) if display_res > 1500: return 1 return 0 # 19 input事件无响应 def inputDispatcher(self, app_arr): for line in app_arr: if 'InputDispatcher: Dropping' in line: return 1 return 0 # 20 亮屏解锁慢 def unlock_slow(self, app_arr): for line in app_arr: if 'Keyguard drawn timeout' in line or 'Timeout waiting for drawn' in line: return 1 return 0 # 21 音频播放卡顿 def audio_slow(self, app_arr): for line in app_arr: if 'E AudioFlinger: writing blocked, write to hal costs:' in line: return 1 return 0 # 22 游戏卡顿 def game_slow(self, app_arr): # 只检测游戏0和游戏4,为了不改动代码,所以直接降其他游戏检测项置零 res = [0, 0, 0, 0, 0, 0, 0, 0] for line in app_arr: game_re = re.compile('gamesdk update status: (.*)').search(line) if game_re: game_tuples = game_re.groups() game_vale = game_tuples[0] dict_game = json.loads(game_vale[1:-1]) if ("pkg" in dict_game) and ("4" in dict_game) and ("12" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["12"] > 150): res[0] = 1 if ("pkg" in dict_game) and ("4" in dict_game) and ("5" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 75) and ( (dict_game["7"] == 90) or (dict_game["7"] == 120) or (dict_game["7"] == 144)): res[1] = 0 if ("pkg" in dict_game) and ("4" in dict_game) and ("5" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 50) and ( dict_game["7"] == 60): res[2] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["4"] == 7) and ( dict_game["5"] < 25) and ( dict_game["7"] == 30): res[3] = 0 if ("pkg" in dict_game) and ("7" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.sgame') and (dict_game["7"] > 150): res[4] = 1 if ("pkg" in dict_game) and ("10" in dict_game) and ("3" in dict_game): if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and (dict_game["10"] == 30) and ( dict_game["3"] < 25): res[5] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and (dict_game["10"] == 60) and ( dict_game["3"] < 50): res[6] = 0 if (dict_game["pkg"] == 'com.tencent.tmgp.pubgmhd') and ( (dict_game["10"] == 90) or (dict_game["10"] == 120) or (dict_game["10"] == 144)) and ( dict_game["3"] < 75): res[7] = 0 return res # jank日志解析 --存储不足,整机lowait,限频,省电模式,高负载,低内存 def jank_log(self, jank_arr): res = [0, 0, 0, 0, 0, 0] for line in jank_arr: freed_re = re.compile('FreeDisk":(.*),').search(line) io_re = re.compile('Iowait":(.*),').search(line) limit_re = re.compile('Limit_Freq":(.*),').search(line) power_re = re.compile('bPowerSavingOn":(.*),').search(line) cpu_re = re.compile('CpuLoad":(.*),').search(line) available_re = re.compile 'AvailableMem":(.*),').search(line) if freed_re: freed_tuples = freed_re.groups() freed_value = freed_tuples[0] if int(freed_value) < 15360: res[0] = 1 if io_re: io_tuples = io_re.groups() io_value = io_tuples[0] if int(io_value) > 80: res[1] = 1 if limit_re: limit_tuples = limit_re.groups() limit_value = limit_tuples[0] if int(limit_value) == 1: res[2] = 0 if power_re: power_tuples = power_re.groups() power_value = power_tuples[0] if (int(power_value) == 1) or (int(power_value) == 4): res[3] = 1 if cpu_re: cpu_tuples = cpu_re.groups() cpu_value = cpu_tuples[0] if int(cpu_value) > 6000: res[4] = 1 if available_re: available_tuples = available_re.groups() available_value = available_tuples[0] if int(available_value) < 819200: res[5] = 1 return res def plugin_preprocess(self, info_dict=None): """ 预处理Hubble传入的info_dict,包含程序运行的基本信息 此函数的基础操作是获取下载日志列表地址,形成task_list任务分析列表,供Hubble调用 """ self.logger.info("这是预处理函数?") task_list = [] download_list = info_dict["common_info"]["log_download_list"] max_analysis_num = 1 # 最多处理几个日志 if len(download_list) > max_analysis_num: download_list = download_list[:max_analysis_num] for download_item in download_list: task_dict = {"download_addr": [], "task_params": {}} task_dict["download_addr
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值