如何将多段try/except代码重构为函数?(JIRA时间转换场景)
重构JIRA毫秒转小时的冗余代码
看起来你已经抓住了问题的核心——重复的try/except块太冗余,而且也找对了方向想用循环批量处理字段,只是卡在了动态字段获取和结果与字段的关联存储上。这里给你一套简洁易维护的重构方案:
第一步:写一个通用的安全属性获取工具函数
JIRA的字段嵌套层级深,还经常出现属性不存在的情况,我们可以把所有异常处理逻辑集中到一个工具函数里,避免重复写try/except:
import numpy as np def convertMillis(ms): try: return ms / 1000 / 60 / 60 except (TypeError, ZeroDivisionError): return np.nan def safe_get(obj, attr_path, default=np.nan): """ 安全获取嵌套属性,支持列表索引(比如'completedCycles[0]') :param obj: 起始对象(比如某个customfield实例) :param attr_path: 嵌套属性路径,用点分隔(比如'completedCycles[0].remainingTime.millis') :param default: 获取失败时的默认值 """ attrs = attr_path.split('.') current = obj for attr in attrs: # 处理列表索引的情况 if '[' in attr and ']' in attr: attr_name, idx_str = attr.split('[') idx = int(idx_str[:-1]) try: current = getattr(current, attr_name)[idx] except (AttributeError, IndexError, TypeError): return default else: try: current = getattr(current, attr) except AttributeError: return default # 最后转换为小时 return convertMillis(current)
第二步:用字典+配置列表批量处理所有字段
不用创建一堆零散的变量,用字典存储结果更灵活;同时用配置列表定义每个字段对应的两个属性路径,新增字段只需加一行配置:
# 定义字段配置:每个元组是(字段名, completed属性路径, ongoing属性路径) field_configs = [ ('customfield_10705', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10136', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10713', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10711', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10140', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10213', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10144', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10134', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_11200', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_10142', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_15600', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ('customfield_15601', 'completedCycles[0].remainingTime.millis', 'ongoingCycle.remainingTime.millis'), ] # 初始化结果字典,存储每个字段的两个计算值 sla_results = {} for field_name, comp_attr, ongoing_attr in field_configs: # 动态获取当前字段对象(解决你之前代码里`issues.fields.field`的错误写法) field_obj = getattr(issues.fields, field_name, None) if not field_obj: # 如果字段不存在,直接设为nan sla_results[f"{field_name}_comp"] = np.nan sla_results[f"{field_name}_ongoing"] = np.nan continue # 安全获取并转换两个值 sla_results[f"{field_name}_comp"] = safe_get(field_obj, comp_attr) sla_results[f"{field_name}_ongoing"] = safe_get(field_obj, ongoing_attr)
第三步:使用结果
现在你可以通过字典键轻松访问每个字段的结果,比如:
# 获取customfield_10705的completed值 print(sla_results['customfield_10705_comp']) # 获取customfield_10136的ongoing值 print(sla_results['customfield_10136_ongoing'])
为什么这个方案更优?
- 彻底消除重复代码:所有异常处理逻辑都集中在
safe_get里,不用重复写几十遍try/except - 维护成本极低:新增字段只需在
field_configs里加一行,不用修改核心逻辑 - 灵活性更强:用字典存储结果,方便后续遍历、转换为DataFrame(如果做数据分析)等操作
- 容错性全面:覆盖了属性不存在、列表索引越界、类型错误等多种异常场景
内容的提问来源于stack exchange,提问作者swifty
相关产品推荐
相关产品推荐

