def apk_generate_key_pair(self, app_id: str) -> tuple: """ 自有AppKey管理工具的生成新密钥对函数(同时可以加入管理工具) @param {str} app_id - 要获取的app_id @returns {tuple} - (app_key, app_secret) 密钥对 """ # 随机生成字符串, app_key 8位, app_secret 32位 _app_key = StringTool.get_random_str(random_length=8) _app_secret = StringTool.get_random_str(random_length=32) self._app_key_manager[app_id] = (_app_key, _app_secret) return (_app_key, _app_secret)
def _start_server_self(self, tid): """ 自定义服务启动函数,实现类可重载该函数加入自己的处理逻辑 重载该函数,实现网络监听服务的启动,但不接收连接 @param {int} tid - 线程id @returns {CResult} - 启动结果: result.code :'00000'-成功,其他值为失败 result.server_info :启动成功后的服务对象,用于传递到后续的服务处理函数 """ _result = CResult(code='00000') # 成功 _result.server_info = NullObj() with ExceptionTool.ignored_cresult(_result): # 可在该部分实现自定义逻辑 self._logger.log( self._log_level, '[%s-STARTING][NAME:%s]%s:\n%s' % ( self._server_log_prefix, self._server_name, _('net start parameter'), StringTool.format_obj_property_str(self._server_opts, is_deal_subobj=True) ) ) # 启动服务,但不接受连接 _result = self._start_server_without_accept(self._server_opts) _result.server_info = _result.net_info # 返回处理结果 return _result
def import_demo_images(self): """ 导入测试图片 """ _index = 1 for _key in IMPORT_URLS: for _url in IMPORT_URLS[_key]: # image_doc信息 _image_doc = { "id": StringTool.fill_fix_string(str(_index), 10, '0'), "url": _url, "path": '' } try: # 下载图片信息 _image = urllib.request.urlopen(_url).read() # 执行导入处理 self.search_engine.image_to_search_db(_image, _image_doc, 'DemoSearch', init_collection='') except: print(traceback.format_exc()) _index += 1
def rename_file_to_num(cls, path: str, start_index: int = 1) -> int: """ 重命名文件为数字序号 @param {str} path - 要处理的文件夹 @param {int} start_index=1 - 开始序号 @returns {int} - 返回当前序号 """ # 处理当前目录 _start_index = start_index _path = os.path.realpath(path) _file_list = FileTool.get_filelist(_path, is_fullname=False) for _file in _file_list: _ext = FileTool.get_file_ext(_file) os.rename( os.path.join(_path, _file), os.path.join( _path, StringTool.fill_fix_string(str(_start_index), 10, '0') + '.' + _ext)) _start_index += 1 # 处理子目录 _sub_dir_list = FileTool.get_dirlist(_path) for _sub_dir in _sub_dir_list: _start_index = cls.rename_file_to_num(_sub_dir, start_index=_start_index) # 返回当前序号值 return _start_index
def _replace_var_fun(m): _match_str = m.group(0) _value = None if _match_str.startswith('{$datetime='): # 按格式化字符替换当前的时间 _key = _match_str[11:-2] _value = datetime.datetime.now().strftime(_key) elif _match_str.startswith('{$uuid='): # 指定uuid字符类型 _key = _match_str[7:-2] str(uuid.uuid1()) _value = eval('str(uuid.uuid%s())' % _key) elif _match_str.startswith('{$random'): # 产生指定两个整数之间的随机数,总位数与最大的数一致,左补零 _key = _match_str[8:-2] _args = eval('(%s)' % _key) _value = StringTool.fill_fix_string( str(random.randint(*_args)), len(_args[1]), '0') elif _match_str.startswith('{$file_ext='): # 原文件扩展名 _value = _file_ext elif _match_str.startswith('{$file_name='): # 原文件指定位置的字符 _key = _match_str[12:-2] _args = eval('(%s)' % _key) if len(_args) > 1: _value = _old_filename[_args[0]:_args[1]] else: _value = _old_filename[_args[0]:] if _value is not None: return str(_value) else: return _match_str
def service_client_side_stream(a, b, *args, **kwargs): """ 测试客户端流模式的服务端应用 """ _ret_obj = [a, b, args, kwargs] _json_str = StringTool.object_to_json(_ret_obj) print('call service_client_side_stream return : ' + _json_str) return [a, b, args, kwargs]
def stream_closed_fun(stream_tag='', stream_obj=None, position=0, closed_status=None): _logger.info( 'stream_closed_fun\nstream_tag: %s\nstream_obj: %s\nposition: %s\nclosed_status: %s' % ( stream_tag, StringTool.format_obj_property_str(stream_obj, is_deal_subobj=True), str(position), closed_status.value ) )
def cmp_dict(cls, src_data, dst_data, print_if_diff=True): """ 比较两个字典是否一致 @param {string/dict} src_data - 第1个字典对象(或对象JSON字符串) @param {string/dict} dst_data - 第2个字典对象(或对象JSON字符串) @param {bool} print_if_diff=True - 当两个字典不一致时是否打印对象信息 @returns {bool} - True-两个字典一致,False-两个字典不一致 """ is_same = False if isinstance(src_data, str): src_data = json.dumps(src_data, ensure_ascii=False) if isinstance(dst_data, str): dst_data = json.dumps(dst_data, ensure_ascii=False) if len(src_data) != len(dst_data): if print_if_diff: print('cmp_dict: len difference!') else: src_key = list(src_data.keys()) src_key.sort() dst_key = list(dst_data.keys()) dst_key.sort() if operator.eq(src_key, dst_key): is_break = False for key in src_data.keys(): if src_data[key] != dst_data[key]: # print(src_data1[key]) print('cmp_dict: value difference in key "%s"!' % (key)) is_break = True break if not is_break: # 如果没有中断过,则代表比较成功 return True else: print('cmp_dict: key list difference!') if print_if_diff: print('src_data :' + StringTool.format_obj_property_str(src_data, is_deal_subobj=True, c_level=2)) print('dst_data :' + StringTool.format_obj_property_str(dst_data, is_deal_subobj=True, c_level=2)) return is_same
def _import_and_init_class(self, module_name, class_name, extend_path, init_para, as_name=''): """ 装载并初始化对象返回(如果对象已存在则直接返回) @param {string} module_name - 模块名 @param {string} class_name - 处理类名 @param {string} extend_path - 模块所在搜索路径 @param {string} init_para - 初始化的json字符串 @param {string} as_name - 对象别名,可以设置不一样的值让类可以多次实例化 @return {object} - 初始化后的模块对象 @throws {ImportError} - 初始化失败返回该异常 """ # 检查对象是否已存在 _key = as_name _class_tag = '%s.%s' % (module_name, class_name) if as_name == '': _key = _class_tag if self._import_object_dict is None: self._import_object_dict = dict() if _key in self._import_object_dict.keys(): # 已存在,直接返回即可 return self._import_object_dict[_key] # 装载模块 _class = None if ImportTool.check_module_imported(module_name): # 模块已存在 _class = ImportTool.get_member_from_module( ImportTool.get_imported_module(module_name), class_name ) else: # 动态装载模块 _class = ImportTool.get_member_from_module( ImportTool.import_module( module_name, extend_path=extend_path ), class_name ) if _class is None: raise ImportError(_("config file error: can't import module: $1!", (_class_tag, ))) # 初始化对象并返回 _init_para = dict() if init_para != '': _init_para = StringTool.json_to_object(init_para) self._import_object_dict[_key] = _class(**_init_para) return self._import_object_dict[_key]
def dealer_exception_fun(stream_tag='', stream_obj=None, deal_obj=None, position=0, dealer_handle=None, error_obj=None, trace_str=''): _logger.info( 'dealer_exception_fun\nstream_tag: %s\nstream_obj: %s\ndeal_obj: %s\nposition: %s\ndealer_handle: %s\nerror_obj: %s\ntrace_str: %s' % ( stream_tag, StringTool.format_obj_property_str(stream_obj, is_deal_subobj=True), str(deal_obj), str(position), str(dealer_handle), str(error_obj), trace_str ) )
def generate_salt( cls, str_len=8, chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"): """ 随机生成盐字符串 @param {int} str_len=8 - 盐长度 @param {string} chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" - 生成盐包含的字符集合 @returns {str} - 生成的盐字符串 """ return StringTool.get_random_str(random_length=str_len, chars=chars)
def compare_object_by_json(object1, object2, logger=None): """ 比较两个基本对象类型(通过转换为json串) @param {object} object1 - 要比较的对象1 @param {object} object2 - 要比较的对象2 @param {logging.Logger} logger=None - 输出日志对象,不一样的时候输出 @return {bool} - 比较是否通过,如果不通过将输出两个对象 """ _json1 = StringTool.object_to_json(object1) _json2 = StringTool.object_to_json(object2) if _json1 == _json2: return True else: # 输出日志 if logger is None: print('object1: ' + _json1) print('object2: ' + _json2) else: logger.error('object1: %s\nobject2: %s' % (_json1, _json2)) return False
def service_server_side_stream(a, b, *args, **kwargs): """ 测试服务端流模式的服务端应用 """ _ret_obj = [a, b, args, kwargs] _json_str = StringTool.object_to_json(_ret_obj) print('call service_server_side_stream return : ' + _json_str) _i = 0 while True: yield [a, b, 'server+' + str(_i), args, kwargs] _i = _i + 1 if _i > 4: break
def labelimg_rename_filename(cls, path: str, fix_len: int = 10): """ 重名名labelimg对应目录下的文件名(图片文件和标注文件同步修改) @param {str} path - 要修改文件名的路径 @param {int} fix_len=10 - 文件名长度 """ _path = os.path.realpath(path) _files = FileTool.get_filelist(path=_path, is_fullname=False) _index = 1 for _file in _files: _file_ext = FileTool.get_file_ext(_file) if _file_ext == 'xml': # 标签文件不处理 continue _file_no_ext = FileTool.get_file_name_no_ext(_file) # 获取最新的文件名 while True: _new_name = StringTool.fill_fix_string(str(_index), fix_len, '0', left=True) _new_file = _new_name + '.' + _file_ext _index += 1 if os.path.exists(os.path.join(path, _new_file)): # 文件名已存在 _index += 1 continue # 文件名不存在,跳出循环 break # 修改文件名 os.rename(os.path.join(_path, _file), os.path.join(_path, _new_file)) if os.path.exists(os.path.join(_path, _file_no_ext + '.xml')): # 需要修改标签文件 _xml_file = _new_name + '.xml' os.rename(os.path.join(_path, _file_no_ext + '.xml'), os.path.join(_path, _xml_file)) # 修改标签文件内容 _tree = ET.parse(os.path.join(_path, _xml_file)) _root = _tree.getroot() _root.find('filename').text = _new_file _root.find('path').text = os.path.join(_path, _new_file) _tree.write(os.path.join(_path, _xml_file), encoding='utf-8', method="xml", xml_declaration=None)
def generate_nonce( cls, length: int = 8, chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789" ) -> str: """ 生成nonce随机字符串 @param {int} length=8 - 要生成的字符串长度 @param {string} chars="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789" - 随机抽取的字符串内容 @returns {str} - 返回随机字符串 """ return StringTool.get_random_str(random_length=length, chars=chars)
def __get_print_str(var_obj): """ 获取对象的打印字符串 @param {object} var_obj - 要打印的对象 @returns {string} - 打印的字符串 """ _print_str = '[type=%s]%s%s' % ( str(type(var_obj)), ('' if not hasattr(var_obj, '__str__') else str(var_obj)), ('' if not hasattr(var_obj, '__dict__') else StringTool.format_obj_property_str(var_obj, is_deal_subobj=True, c_level=2)) ) return _print_str
def default_formula_deal_fun_id(formular_obj, **kwargs): """ 默认公式计算函数-格式化id(左补0) @param {StructFormula} formular_obj - 要计算的公式 @param {kwargs} - 处理公式的参数,必须传进来的参数为 id {int} - 要格式化的id """ if formular_obj.content_string == '': formular_obj.formula_value = str(kwargs['id']) else: formular_obj.formula_value = StringTool.fill_fix_string( str(kwargs['id']), fix_len=int(formular_obj.content_string), fill_char='0')
def service_bidirectional_stream(a, b, *args, **kwargs): """ 测试双向流模式的服务端应用 """ _ret_obj = [a, b, args, kwargs] _json_str = StringTool.object_to_json(_ret_obj) print('call service_bidirectional_stream get : ' + _json_str) if a == 'one': # 一个请求一个回应的方式,只回复单个内容 yield [a, b, 'one-->', args, kwargs] elif a == 'end': # 收到请求,只要不是最后一个,回应None if b == 'end': yield [a, b, 'end-->', args, kwargs] else: yield None else: # 其他情况,一个回应多个 _i = 0 while True: yield [a, b, 'bidirectional+' + str(_i), args, kwargs] _i = _i + 1 if _i > 4: break
def console_main(execute_file_path=None, default_config_file=None, console_self_config: dict = None, **kwargs): """ 启动命令行框架的主函数 @param {string} execute_file_path=None - 外部调用该函数应将程序主目录传入,这样才能找到配置文件 @param {string} default_config_file=None - 如果您希望用不同的配置文件路径作为默认路径,可传入该函数指定 @param {dict} console_self_config=None - 命令行自定义配置信息,将添加到全局参数中 """ # 获取命令行参数,需要外部传入config、encoding参数 # 例如 console.py config=/conf/config.xml encoding=utf-8 help=y shell_cmd=以命令行方式执行命令 shell_cmdfile=cmdfile.txt cmdfile_encoding=utf-8 CONSOLE_GLOBAL_PARA = RunTool.get_global_var('CONSOLE_GLOBAL_PARA') if CONSOLE_GLOBAL_PARA is None: CONSOLE_GLOBAL_PARA = {} RunTool.set_global_var('CONSOLE_GLOBAL_PARA', CONSOLE_GLOBAL_PARA) # 自定义配置信息 CONSOLE_GLOBAL_PARA['console_self_config'] = console_self_config # 程序主目录 if execute_file_path is None: CONSOLE_GLOBAL_PARA['execute_file_path'] = os.path.realpath( FileTool.get_file_path(__file__)) else: CONSOLE_GLOBAL_PARA['execute_file_path'] = execute_file_path # 工作目录,可以通过cd命令切换,通过pwd命令查看工作目录路径 CONSOLE_GLOBAL_PARA['work_path'] = os.getcwd() _cmd_opts = RunTool.get_kv_opts() _default_config_file = default_config_file if _default_config_file is None: _default_config_file = os.path.join( CONSOLE_GLOBAL_PARA['execute_file_path'], 'conf/config.xml') _config = ( _default_config_file ) if 'config' not in _cmd_opts.keys() else _cmd_opts['config'] _encoding = 'utf-8' if 'encoding' not in _cmd_opts.keys() else _cmd_opts['encoding'] CONSOLE_GLOBAL_PARA['config_encoding'] = _encoding CONSOLE_GLOBAL_PARA['config_file'] = _config # 获取配置文件信息 _config_xml = SimpleXml(os.path.realpath(_config), encoding=_encoding) _config_dict = _config_xml.to_dict() # 启动控制台服务 _server = ConsoleServer(_config_dict['console']) # 判断是否 if 'help' in _cmd_opts.keys(): # 执行帮助命令 _lang = _config_dict['console']['language'] _help_tips = StringTool.json_to_object( _config_dict['console']['shell_cmd_help'] ) _tips = '' # 如果找不到对应的语言,优先找英语,如果再找不到就找第一个 if _lang in _help_tips.keys(): _tips = _help_tips[_lang] elif 'en' in _help_tips.keys(): _tips = _help_tips['en'] else: _tips = _help_tips[_help_tips.keys()[0]] _print_str = '\r\n'.join(_tips).replace( '{{VERSION}}', _config_dict['console']['version'] ).replace( '{{NAME}}', _config_dict['console']['name'] ).replace( '{{SHELL_CMD_NAME}}', _config_dict['console']['shell_cmd_name'] ) # 打印 print(_print_str) elif 'shell_cmd' in _cmd_opts.keys(): # 命令行模式执行 _cmd_list = None if _cmd_opts['shell_cmd'][0: 1] == '[' and _cmd_opts['shell_cmd'][-1:] == ']': # 是json数组格式 _cmd_list = StringTool.json_to_object(_cmd_opts['shell_cmd']) else: _cmd_list = [_cmd_opts['shell_cmd']] # 逐个命令执行 for _cmd in _cmd_list: _result = _server.call_cmd_directly(_cmd, shell_cmd=True) if not _result.is_success(): # 执行有错误,不继续执行 exit(1) # 正常完成 exit(0) elif 'shell_cmdfile' in _cmd_opts.keys(): _file_encoding = None if 'cmdfile_encoding' in _cmd_opts.keys() and _cmd_opts['cmdfile_encoding'] != '': _file_encoding = _cmd_opts['cmdfile_encoding'] _cmd_text = FileTool.get_file_text(_cmd_opts['shell_cmdfile'], encoding=_file_encoding) _cmd_text = _cmd_text.replace('\r\n', '\n').replace('\r', '\n') _cmd_list = _cmd_text.split('\n') # 逐个命令执行 for _cmd in _cmd_list: _result = _server.call_cmd_directly(_cmd, shell_cmd=True) if not _result.is_success(): # 执行有错误,不继续执行 exit(1) # 正常完成 exit(0) else: _server.start_console()
def _init_cmd_paras(self): """ 初始化控制台参数 实现self._CMD_HELP_INFO和self._CMD_PARA字典的装载 """ if self._CMD_LIST is None: self._CMD_LIST = dict() else: self._CMD_LIST.clear() if self._CMD_HELP_INFO is None: self._CMD_HELP_INFO = dict() else: self._CMD_HELP_INFO.clear() if self._CMD_PARA is None: self._CMD_PARA = dict() else: self._CMD_PARA.clear() self._auto_run_fun = None if 'auto_run' in self._config_dict.keys() and self._config_dict['auto_run']['class_name'] != '': # 装载执行函数 self._auto_run_fun = self._import_and_init_class( self._config_dict['auto_run']['module_name'], self._config_dict['auto_run']['class_name'], self._config_dict['auto_run']['extend_path'], self._config_dict['auto_run']['init_para'], as_name='' if 'as_name' not in self._config_dict.keys( ) else self._config_dict['as_name'] ).cmd_dealfun # 遍历cmd_list进行装载命令参数 for _item in self._config_dict['cmd_list']: # 检查help命令是否自带命令 if _item['command'] == 'help' and _item['module_name'] == 'HiveNetLib.simple_console.base_cmd': self._is_fw_help_command = True # 命令清单 self._CMD_LIST[_item['command']] = None try: # 帮助信息 self._CMD_HELP_INFO[_item['command']] = StringTool.json_to_object(_item['help']) except Exception as e: print('config file cmd [%s] help json string error!' % _item['command']) raise e try: # 命令信息 self._CMD_PARA[_item['command']] = StringTool.json_to_object(_item['cmd_para']) except Exception as e: print('config file cmd [%s] cmd_para json string error!' % _item['command']) raise e # 处理函数 self._CMD_PARA[_item['command']]['deal_fun'] = self._import_and_init_class( _item['module_name'], _item['class_name'], _item['extend_path'], _item['init_para'], as_name='' if 'as_name' not in _item.keys() else _item['as_name'] ).cmd_dealfun
def server_connect_deal_fun(cls, thread_id, server_opts, net_info, self_tag): cls.logger.log( simple_log.INFO, "[服务端" + self_tag + "][" + str(thread_id) + "]收到客户端连接:" + StringTool.format_obj_property_str( deal_obj=net_info, is_deal_subobj=True)) # 获取客户端发送的信息,先获取前4个字节 _read_result = TcpIpService.recv_data(net_info, {'recv_len': 4}) if _read_result.code != '00000': # 获取失败 cls.logger.log(simple_log.INFO, ("[服务端]获取客户端数据报文头失败,关闭连接:" + str(_read_result.code) + "-" + _read_result.msg)) TcpIpService.close_connect(net_info) return _next_read = int.from_bytes(_read_result.data, byteorder='big', signed=False) cls.logger.log(simple_log.INFO, "[服务端]获取到客户端4个字节的后续数据长度:" + str(_next_read)) # 获取后面的数据 _read_result = TcpIpService.recv_data(net_info, {'recv_len': _next_read}) if _read_result.code != '00000': # 获取失败 cls.logger.log(simple_log.INFO, ("[服务端]获取客户端数据报文体失败,关闭连接:" + str(_read_result.code) + "-" + _read_result.msg)) TcpIpService.close_connect(net_info) return _read_str = str(_read_result.data, "utf-8") cls.logger.log(simple_log.INFO, "[服务端]获取到客户端报文体数据:" + _read_str) if _read_str == "servernoresponse": # 隔30秒不响应 time.sleep(30) # 返回内容,先组包 _ret_str = "处理成功" _send_body = bytes(_ret_str, "utf-8") _send_head = len(_send_body).to_bytes(4, byteorder='big', signed=False) # 发送报文头 _send_result = TcpIpService.send_data(net_info, _send_head, {}) if _send_result.code != '00000': cls.logger.log(simple_log.INFO, ("[服务端]返回客户端数据报文头失败,关闭连接:" + str(_send_result.code) + "-" + _send_result.msg)) TcpIpService.close_connect(net_info) return cls.logger.log(simple_log.INFO, "[服务端]返回客户端4个字节的后续数据长度:" + str(len(_send_body))) _send_result = TcpIpService.send_data(net_info, _send_body, {}) if _send_result.code != '00000': cls.logger.log(simple_log.INFO, ("[服务端]返回客户端数据报文体失败,关闭连接:" + str(_send_result.code) + "-" + _send_result.msg)) TcpIpService.close_connect(net_info) return cls.logger.log(simple_log.INFO, "[服务端]返回客户端报文体数据:" + _ret_str) # 处理完成,关闭连接 _close_result = TcpIpService.close_connect(net_info) if _close_result.code != '00000': cls.logger.log(simple_log.INFO, ("[服务端]关闭客户端连接失败:" + str(_close_result.code) + "-" + _close_result.msg)) cls.logger.log(simple_log.INFO, "[服务端]关闭客户端连接")
def __init__(self, config_dict): """ 初始化构造函数 @param {dict} server_config_dict - 服务器的初始化参数字典(console节点) """ # 初始化参数 self._config_dict = copy.deepcopy(config_dict) # 将部分公共参数放到全局变量 self._console_global_para = RunTool.get_global_var('CONSOLE_GLOBAL_PARA') self._console_global_para['name'] = self._config_dict['name'] self._console_global_para['version'] = self._config_dict['version'] self._console_global_para['shell_cmd_name'] = self._config_dict['shell_cmd_name'] self._console_global_para['language'] = self._config_dict['language'] self._console_global_para['shell_encoding'] = self._config_dict['shell_encoding'] # 控制台编码 self._console_global_para['exit_with_prompt'] = self._config_dict.get( 'exit_with_prompt', 'y') # 是否提示退出 # i18n多语言加载 _trans_file_path = None if self._config_dict['i18n'] == '': _trans_file_path = os.path.join( self._console_global_para['execute_file_path'], 'i18n/' ) else: _trans_file_path = self._config_dict['i18n'] _i18n_obj: SimpleI18N = get_global_i18n() if _i18n_obj is None: _i18n_obj = SimpleI18N( lang=self._config_dict['language'], trans_file_path=_trans_file_path, trans_file_prefix='message', auto_loads=True ) else: # 装载默认的多国语言 _i18n_obj.load_trans_from_dir( _trans_file_path, 'message', encoding='utf-8', append=True ) _i18n_obj.lang = self._config_dict['language'] # 再装载自身命令的国际语言文件 _i18n_obj.load_trans_from_dir( os.path.join(os.path.realpath(FileTool.get_file_path(__file__)), 'i18n/'), 'message', encoding='utf-8', append=True ) set_global_i18n(_i18n_obj) # 装载默认执行函数 _temp_dict = self._config_dict['default_dealfun'] self._default_cmd_dealfun = self._import_and_init_class( _temp_dict['module_name'], _temp_dict['class_name'], _temp_dict['extend_path'], _temp_dict['init_para'], as_name='' if 'as_name' not in _temp_dict.keys() else _temp_dict['as_name'] ).cmd_dealfun _temp_dict = self._config_dict['on_abort'] self._on_abort = self._import_and_init_class( _temp_dict['module_name'], _temp_dict['class_name'], _temp_dict['extend_path'], _temp_dict['init_para'], as_name='' if 'as_name' not in _temp_dict.keys() else _temp_dict['as_name'] ).cmd_dealfun _temp_dict = self._config_dict['on_exit'] self._on_exit = self._import_and_init_class( _temp_dict['module_name'], _temp_dict['class_name'], _temp_dict['extend_path'], _temp_dict['init_para'], as_name='' if 'as_name' not in _temp_dict.keys() else _temp_dict['as_name'] ).cmd_dealfun # 遍历参数装载 self._is_fw_help_command = False self._init_cmd_paras() # 加入到CONSOLE_GLOBAL_PARA参数中 self._console_global_para['CMD_PARA'] = self._CMD_PARA self._console_global_para['CMD_HELP_INFO'] = self._CMD_HELP_INFO self._console_global_para['CMD_LIST'] = self._CMD_LIST # 检查help命令是否框架自带的,如果是则增加提示帮助 if self._is_fw_help_command: self._CMD_PARA['help']['word_para'] = self._CMD_LIST # 控制台启动时的提示语言 self._CONSOLE_TIPS = StringTool.json_to_object(self._config_dict['start_tips']) # 日志对象 _logger = None if 'logger' in self._config_dict.keys(): _logger = Logger.create_logger_by_dict( self._config_dict['logger']) # 颜色调整 _color_set = self._config_dict.get('color_set', None) if _color_set is not None: _input_color = _color_set.get('input', None) if _input_color is not None: _color_set[''] = _input_color # 初始化命令行工具对象 self._prompt = PromptPlus( message=self._config_dict['message'], default='', # 默认输入值 cmd_para=self._CMD_PARA, # 命令定义参数 default_dealfun=self._default_cmd_dealfun, # 默认处理函数 on_abort=self._on_abort, # Ctrl + C 取消本次输入执行函数 on_exit=self._on_exit, # Ctrl + D 关闭命令行执行函数 logger=_logger, # 日志 color_set=_color_set, # 命令行配色方案 ) # 最后才添加这个对象 self._console_global_para['prompt_obj'] = self._prompt # 将命令行工具对象放到可访问的参数中 # 执行命令处理类的后初始化函数 for _key in self._import_object_dict.keys(): if hasattr(self._import_object_dict[_key], 'init_after_console_init'): self._import_object_dict[_key].init_after_console_init()
def _help_cmd_dealfun(self, message='', cmd='', cmd_para='', prompt_obj=None, **kwargs): """ 帮助命令处理函数 @param {string} message='' - prompt提示信息 @param {string} cmd - 执行的命令key值 @param {string} cmd_para - 传入的命令参数(命令后的字符串,去掉第一个空格) @param {PromptPlus} prompt_obj=None - 传入调用函数的PromptPlus对象,可以通过该对象的一些方法控制输出显示 @param {kwargs} - 传入的主进程的初始化kwargs对象 @returns {CResult} - 命令执行结果,可通过返回错误码10101通知框架退出命令行, 同时也可以通过CResult对象的 print_str属性要求框架进行打印处理 """ # 命令相关参数 _CMD_HELP_INFO = self._console_global_para['CMD_HELP_INFO'] _lang = self._console_global_para['language'] _cmd_list = PromptPlus.get_cmd_para_list(cmd_para) if len(_cmd_list) == 0: # 没有传入任何参数,生成命令提示参数并返回 # 先计算命令的最大长度 _max_len = 15 for _key in _CMD_HELP_INFO.keys(): _max_len = max(_max_len, len(_key)) _cmd_list_tips = '' for _key in _CMD_HELP_INFO.keys(): _cmd_title = '' if _lang in _CMD_HELP_INFO[_key].keys(): _cmd_title = _CMD_HELP_INFO[_key][_lang][0] elif 'en' in _CMD_HELP_INFO[_key].keys(): _cmd_title = _CMD_HELP_INFO[_key]['en'][0] else: _cmd_title = _CMD_HELP_INFO[_key][list( _CMD_HELP_INFO[_key].keys())[0]][0] _cmd_list_tips = '%s%s%s\n' % ( _cmd_list_tips, StringTool.fill_fix_string( _key, _max_len + 1, ' ', left=False), _cmd_title.replace( '{{VERSION}}', self._console_global_para['version']).replace( '{{NAME}}', self._console_global_para['name']).replace( '{{SHELL_CMD_NAME}}', self._console_global_para['shell_cmd_name'])) # 返回提示信息 return _cmd_list_tips # 处理某个命令的具体帮助信息 _para_value = '' for _item in _cmd_list: if _item[0] == '': _para_value = _item[1] break elif _item[0] == '-c' or _item[0] == '-cmd': _para_value = _item[1] break if _para_value in _CMD_HELP_INFO.keys(): # 显示指定命令帮助 _help_info = None if _lang in _CMD_HELP_INFO[_para_value].keys(): _help_info = _CMD_HELP_INFO[_para_value][_lang] elif 'en' in _CMD_HELP_INFO[_para_value].keys(): _help_info = _CMD_HELP_INFO[_para_value]['en'] else: _help_info = _CMD_HELP_INFO[_para_value][list( _CMD_HELP_INFO[_para_value].keys())[0]] prompt_obj.prompt_print('\n'.join(_help_info).replace( '{{VERSION}}', self._console_global_para['version']).replace( '{{NAME}}', self._console_global_para['name']).replace( '{{SHELL_CMD_NAME}}', self._console_global_para['shell_cmd_name'])) else: # 没有匹配到命令 prompt_obj.prompt_print( _("help not support '$1' command\n", (_para_value, ))) # 返回结果 return CResult(code='00000')
def labelimg_crop_pic_by_flags(cls, path: str, dest_path: str, copy_no_flag_pic: bool = True, with_sub_dir: bool = True, fix_len: int = 10): """ 根据标注进行图片截图处理 @param {str} path - 需要处理的目录 @param {str} dest_path - 截图图片存放目录 @param {bool} copy_no_flag_pic=True - 直接复制没有标注的图片 @param {bool} with_sub_dir=True - 是否按原目录结构存储图片 @param {int} fix_len=10 - 图片重命名的文件名长度 @returns {iter_list} - 通过yield返回的处理进度信息清单 [总文件数int, 当前已处理文件数int, 是否成功] """ try: # 获取所有要处理的图片清单 _file_list = cls._get_pic_file_list(path) _total = len(_file_list) _deal_num = 0 # 先返回进度情况 if _total == 0: yield [_deal_num, _total, True] return # 创建复制文件夹 FileTool.create_dir(dest_path, exist_ok=True) # 遍历处理 _rename_index = 1 _src_path = os.path.realpath(path) _dest_path = os.path.realpath(dest_path) for _file in _file_list: # 当前进展 yield [_deal_num, _total, True] # 路径处理 _file_path, _filename = os.path.split(_file) if with_sub_dir: # 创建子目录 _dest_path = os.path.join( os.path.realpath(dest_path), os.path.realpath(_file_path)[len(_src_path):].strip( '/\\')) FileTool.create_dir(_dest_path, exist_ok=True) # 获取标注文件 _ext = FileTool.get_file_ext(_filename) _xml_file = os.path.join(_file_path, _filename[0:-len(_ext)] + 'xml') if not os.path.exists(_xml_file): # 标注文件不存在 if copy_no_flag_pic: # 直接复制文件 shutil.copy( _file, os.path.join( _dest_path, StringTool.fill_fix_string( str(_rename_index), fix_len, '0') + '.' + _ext)) _rename_index += 1 # 下一个 _deal_num += 1 continue # 将图片放入内存 with open(_file, 'rb') as _fid: _file_bytes = _fid.read() _image = Image.open(BytesIO(_file_bytes)) # 处理标注 _tree = ET.parse(_xml_file) _root = _tree.getroot() for _member in _root.findall('object'): # 逐个标注进行处理 _crop_image = _image.crop( (int(_member[4][0].text), int(_member[4][1].text), int(_member[4][2].text), int(_member[4][3].text))) _crop_image.save(os.path.join( _dest_path, StringTool.fill_fix_string(str(_rename_index), fix_len, '0') + '.' + _ext), format='JPEG') _rename_index += 1 # 下一个 _deal_num += 1 # 返回结果 yield [_total, _total, True] except: print('labelimg_crop_pic_by_flags error: %s\r\n%s' % (path, traceback.format_exc())) yield [-1, -1, False]