示例#1
0
    def recv_data(cls, net_info, recv_para={}):
        """
        从指定的网络连接中读取数据

        @param {object} net_info - 要读取数据的网络信息对象(例如socket对象)
        @param {dict} recv_para - 读取数据的参数, 包括:
            recv_len {int} - 要获取的数据长度, 必要参数
            overtime {int} - 获取超时时间,单位为毫秒,非必要参数

        @returns {CResult} - 数据获取结果:
            result.code :'00000'-成功,'20403'-获取数据超时,其他为获取失败
            result.data :获取到的数据对象(具体类型和定义,由实现类自定义)
            result.recv_time : datetime 实际开始接受数据时间
            result.overtime : int 超时时间(毫秒),当返回结果为超时,可获取超时时间信息

        """
        # 子类必须定义该功能
        if type(recv_para) != dict:
            recv_para = {}
        _result = CResult('00000')
        _result.data = b''
        _result.recv_time = datetime.datetime.now()
        _overtime = 10000
        if 'overtime' in recv_para.keys():
            # 外部有传入,优先使用该超时时间
            _overtime = recv_para['overtime']
        elif hasattr(net_info, 'recv_timeout'):
            # 如果net_info有超时的设置
            _overtime = net_info.recv_timeout
        _result.overtime = _overtime

        with ExceptionTool.ignored_cresult(
            _result
        ):
            _rest_bytes = recv_para['recv_len']
            while _rest_bytes > 0:
                # 检查是否超时
                if (datetime.datetime.now() - _result.recv_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20403')
                    break

                _buffer = b''
                with ExceptionTool.ignored(expect=(BlockingIOError)):
                    # 获取数据
                    _buffer = net_info.csocket.recv(_rest_bytes)
                    if len(_buffer) > 0:
                        _result.data = _result.data + _buffer
                        _rest_bytes = _rest_bytes - len(_buffer)
                    else:
                        # 休眠一下
                        RunTool.sleep(0.001)
        return _result
示例#2
0
    def send_data(cls, net_info, data, send_para={}):
        """
        向指定的网络连接发送数据

        @param {object} net_info - 要写入数据的网络信息对象(例如socket对象)
        @param {object} data - 要写入的数据对象(具体类型和定义,由实现类自定义)
        @param {dict} send_para - 写入数据的参数:
            overtime {int} - 发送超时时间,单位为毫秒, 非必须参数
        @returns {CResult} - 发送结果:
            result.code :'00000'-成功,'20404'-写入数据超时,其他为写入失败
            result.send_time : datetime 实际发送完成时间
            result.overtime : int 超时时间(毫秒),当返回结果为超时,可获取超时时间信息

        """
        # 子类必须定义该功能
        if type(send_para) != dict:
            send_para = {}
        _result = CResult('00000')
        _result.send_time = None
        _overtime = 10000
        if 'overtime' in send_para.keys():
            _overtime = send_para['overtime']
        elif hasattr(net_info, 'send_timeout'):
            # 如果net_info有超时的设置
            _overtime = net_info.send_timeout
        _result.overtime = _overtime

        _begin_time = datetime.datetime.now()

        with ExceptionTool.ignored_cresult(
            _result
        ):
            _rest_bytes = len(data)
            _total_bytes = _rest_bytes
            while _rest_bytes > 0:
                # 检查是否超时
                if (datetime.datetime.now() - _begin_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20404')
                    break
                with ExceptionTool.ignored(expect=(BlockingIOError)):
                    # 发送数据
                    _len = net_info.csocket.send(data[_total_bytes - _rest_bytes:])
                    if _len > 0:
                        _rest_bytes = _rest_bytes - _len

            _result.send_time = datetime.datetime.now()
        return _result
示例#3
0
    def ignored_cresult(result_obj=None,
                        error_map={},
                        expect=(),
                        expect_no_log=False,
                        expect_use_error_map=True,
                        logger=None,
                        self_log_msg='',
                        force_log_level=None,
                        i18n_obj=None,
                        i18n_msg_paras=(),
                        debug=False):
        """
        忽略异常并设置CResult对象,简化异常捕获代码,利用该函数忽略指定的异常,并设置传入的通用结果对象,详细说明如下:
            1、对于指定忽略的异常,忽略不处理,结果为成功(如果指定logger则会进行日志输出,使用WARNING级别)
            2、对于非指定的异常,不抛出异常,结果为失败(如果指定logger则会进行日志输出,使用ERROR级别)
            3、输出的日志为self_log_msg+'\n'+trace_str
            4、根据error_map的映射关系设置错误码和错误信息

        @param {CResult} result_obj=None - 需要设置的错误类对象(对象值会被修改)
        @param {dict} error_map={} - 用来设置错误类对象的映射表,具体说明如下:
            1、key为异常类,value为(code, msg)的错误码、错误描述二元组,如果msg=None代表使用标准错误码
            2、应有一个'DEFAULT'的key,代表没有匹配上的异常映射,默认value为('29999', None)
            3、应有一个'SUCESS'的key,代表成功的映射,默认value为('00000', None)
            注:value也可以为(code, msg, i18n_msg_paras)的错误码、错误描述、国际化替换参数三元组,
                i18n_msg_paras为tuple类型, 使用该模式支持CResult的国际化处理
        @param {tuple} expect=() - 需要忽略的异常列表,例如(ZeroDivisionError, ValueError)
        @param {bool} expect_no_log=False - 忽略异常列表是否不打印日志
        @param {bool} expect_use_error_map=True - 忽略异常列表所匹配到的异常,所返回错误码是否使用错误码映射表:
            如果在映射表中匹配上则返回映射表的错误码;匹配不上则返回成功
        @param {object} logger=None - 日志对象,如果为None代表不需要输出日志,传入对象需满足:
            1、标准logging的logger对象
            2、自定义的日志类对象,但应实现warning、error的标准方法
        @param {string} self_log_msg='' - 需要输出的自定义日志信息
        @param {int} force_log_level=None - 强制遇到所有异常统一按指定的日志级别输出(logging.INFO/...)
        @param {object} i18n_obj=None - 国际化类的实例对象,该对象需实现translate方法
        @param {tuple} i18n_msg_paras=() - 与self_log_msg配套使用,当使用国际化时,可以传入变量,用于替换self_log_msg中的$1占位符
        @param {bool} - debug=False - 是否调试模式,如果是调试模式,当没有logger时使用print输出堆栈信息

        @example
            result = CResult()
            with ExceptionTools.ignored_CResult(result_obj=result, error_map={},expect=(),logger=None,self_log_msg=''):
                i = 1/0
                i = i + 1000
            print(str(result))

        """
        _error_map = copy.deepcopy(error_map)
        try:
            # 初始化对象
            if result_obj is None:
                result_obj = CResult(code='00000', msg=None, i18n_obj=i18n_obj)

            # 确保映射表中有默认值
            if 'SUCESS' not in _error_map.keys():
                _error_map['SUCESS'] = ('00000', None, i18n_msg_paras)
            if 'DEFAULT' not in _error_map.keys():
                _error_map['DEFAULT'] = ('29999', None, i18n_msg_paras)
            # 执行with对应的脚本
            yield
        except expect as ex:
            # 匹配到指定异常,输出日志
            if not expect_no_log:
                _log_level = logging.WARNING
                if force_log_level is not None:
                    _log_level = force_log_level
                _self_log_msg = ''
                if i18n_obj is not None:
                    _self_log_msg = i18n_obj.translate(
                        self_log_msg, replace_para=i18n_msg_paras)
                else:
                    _self_log_msg = _(self_log_msg, *i18n_msg_paras)
                ExceptionTool.__print_log(logger=logger,
                                          self_log_msg='[EX:%s]%s' %
                                          (str(type(ex)), _self_log_msg),
                                          trace_str=traceback.format_exc(),
                                          log_level=_log_level,
                                          debug=debug)
            # 按成功处理
            _error = sys.exc_info()
            _trace_str = traceback.format_exc()
            if expect_use_error_map and _error[0] in _error_map.keys():
                if len(_error_map[_error[0]]) < 3:
                    result_obj.change_code(code=_error_map[_error[0]][0],
                                           msg=_error_map[_error[0]][1])
                else:
                    result_obj.change_code(
                        code=_error_map[_error[0]][0],
                        msg=_error_map[_error[0]][1],
                        i18n_msg_paras=_error_map[_error[0]][2])
                result_obj.error = str(_error[0])
                result_obj.trace_str = _trace_str
            else:
                # 按成功处理
                pass
        except Exception as e:
            # 其他异常,输出日志,获取失败信息
            _error = sys.exc_info()
            _trace_str = traceback.format_exc()
            if _error[0] in _error_map.keys():
                if len(_error_map[_error[0]]) < 3:
                    result_obj.change_code(code=_error_map[_error[0]][0],
                                           msg=_error_map[_error[0]][1])
                else:
                    result_obj.change_code(
                        code=_error_map[_error[0]][0],
                        msg=_error_map[_error[0]][1],
                        i18n_msg_paras=_error_map[_error[0]][2])
                result_obj.error = str(_error[0])
                result_obj.trace_str = _trace_str
            else:
                # 其他失败
                if len(_error_map['DEFAULT']) < 3:
                    result_obj.change_code(code=_error_map['DEFAULT'][0],
                                           msg=_error_map['DEFAULT'][1])
                else:
                    result_obj.change_code(
                        code=_error_map['DEFAULT'][0],
                        msg=_error_map['DEFAULT'][1],
                        i18n_msg_paras=_error_map['DEFAULT'][2])
                result_obj.error = str(_error[0])
                result_obj.trace_str = _trace_str

            _log_level = logging.ERROR
            if force_log_level is not None:
                _log_level = force_log_level
            _self_log_msg = ''
            if i18n_obj is not None:
                _self_log_msg = i18n_obj.translate(self_log_msg,
                                                   replace_para=i18n_msg_paras)
            else:
                _self_log_msg = _(self_log_msg, *i18n_msg_paras)
            ExceptionTool.__print_log(logger=logger,
                                      self_log_msg='[EX:%s]%s' %
                                      (str(type(e)), _self_log_msg),
                                      trace_str=result_obj.trace_str,
                                      log_level=_log_level,
                                      debug=debug)
示例#4
0
    def recv_http_head(cls, net_info, recv_para={}):
        """
        获取http报文头对象

        @param {object} net_info -  要读取数据的网络信息对象
        @param {dict} recv_para - 获取参数,暂未使用

        @returns {CResult} - 数据获取结果:
            result.code :'00000'-成功,'20403'-获取数据超时,其他为获取失败
            result.data :获取到的数据对象,类型为MsgHTTP
            result.recv_time : datetime 实际开始接受数据时间

        """
        if type(recv_para) != dict:
            recv_para = {}
        _result = CResult('00000')
        _result.data = None
        _result.recv_time = datetime.datetime.now()
        _overtime = 10000
        if 'overtime' in recv_para.keys():
            # 外部有传入,优先使用该超时时间
            _overtime = recv_para['overtime']
        elif hasattr(net_info, 'recv_timeout'):
            # 如果net_info有超时的设置
            _overtime = net_info.recv_timeout
        _result.overtime = _overtime

        _recv_para = copy.deepcopy(recv_para)
        _recv_para['recv_len'] = 1

        with ExceptionTool.ignored_cresult(
            _result
        ):
            # 循环获取所有报文头内容
            _get_line_bytes = b''
            _last_is_ln = False  # 标记上一个字符是否回车换行
            while True:
                # 检查是否超时
                if (datetime.datetime.now() - _result.recv_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20403')
                    break

                _read_result = TcpIpService.recv_data(net_info, _recv_para)
                if not _read_result.is_success():
                    # 出现异常,直接返回失败
                    _read_result.data = None
                    _read_result.recv_time = _result.recv_time
                    return _read_result
                # 获取成功,判断是否回车换行
                _get_line_bytes = _get_line_bytes + _read_result.data
                if str(_read_result.data, "ascii") == "\n" and _last_is_ln:
                    # 已经连续遇到两次回车换行,说明报文头已收齐退出循环
                    break
                elif str(_read_result.data, "ascii") == "\n":
                    _last_is_ln = True
                    continue
                elif str(_read_result.data, "ascii") == "\r":
                    continue
                else:
                    # 其他字符,不是连续换行
                    _last_is_ln = False
                    continue
            # 取完报文头数据,转换为结构对象
            _result.data = MsgHTTP(_get_line_bytes, msg_id=None, obj_type=EnumMsgObjType.Bytes)
        return _result