Преобразование нескольких блоков try / кроме в функцию - PullRequest
0 голосов
/ 31 мая 2018

Это более общий вопрос программирования, чем связанный с реальным кодом.

У меня есть этот уродливый код, который принимает входные данные из JIRA и преобразует их из миллисекунд в часы, записанные несколько раз, как показано ниже:

def convertMillis(ms):
    hours = ms / 1000 / 60 / 60
    return hours

try:
    newaccsla_comp = convertMillis(issues.fields.customfield_10705.completedCycles[0].remainingTime.millis)
except:
    newaccsla_comp = np.nan
try:
    newaccsla_ongoing = convertMillis(issues.fields.customfield_10705.ongoingCycle.remainingTime.millis)
except:
    newaccsla_ongoing = np.nan

try:
    paymentssla_comp = convertMillis(issues.fields.customfield_10136.completedCycles[0].remainingTime.millis)
except:
    paymentssla_comp = np.nan
try:
    paymentssla_ongoing = convertMillis(issues.fields.customfield_10136.ongoingCycle.remainingTime.millis)
except:
    paymentssla_ongoing = np.nan

try:
    modifysla_comp = convertMillis(issues.fields.customfield_10713.completedCycles[0].remainingTime.millis)
except:
    modifysla_comp = np.nan
try:
    modifysla_ongoing = convertMillis(issues.fields.customfield_10713.ongoingCycle.remainingTime.millis)
except:
    modifysla_ongoing = np.nan

try:
    MFsla_comp = convertMillis(issues.fields.customfield_10711.completedCycles[0].remainingTime.millis)
except:
    MFsla_comp = np.nan
try:
    MFsla_ongoing = convertMillis(issues.fields.customfield_10711.ongoingCycle.remainingTime.millis)
except:
    MFsla_ongoing = np.nan

try:
    closeaccsla_comp = convertMillis(issues.fields.customfield_10140.completedCycles[0].remainingTime.millis)
except:
    closeaccsla_comp = np.nan
try:
    closeaccsla_ongoing = convertMillis(issues.fields.customfield_10140.ongoingCycle.remainingTime.millis)
except:
    closeaccsla_ongoing = np.nan

try:
    casla_comp = convertMillis(issues.fields.customfield_10213.completedCycles[0].remainingTime.millis)
except:
    casla_comp = np.nan
try:
    casla_ongoing = convertMillis(issues.fields.customfield_10213.ongoingCycle.remainingTime.millis)
except:
    casla_ongoing = np.nan

try:
    at_comp = convertMillis(issues.fields.customfield_10144.completedCycles[0].remainingTime.millis)
except:
    at_comp = np.nan
try:
    at_ongoing = convertMillis(issues.fields.customfield_10144.ongoingCycle.remainingTime.millis)
except:
    at_ongoing = np.nan

try:
    modfeesla_comp = convertMillis(issues.fields.customfield_10134.completedCycles[0].remainingTime.millis)
except:
    modfeesla_comp = np.nan
try:
    modfeesla_ongoing = convertMillis(issues.fields.customfield_10134.ongoingCycle.remainingTime.millis)
except:
    modfeesla_ongoing = np.nan

try:
    tdsla_comp = convertMillis(issues.fields.customfield_11200.completedCycles[0].remainingTime.millis)
except:
    tdsla_comp = np.nan
try:
    tdsla_ongoing = convertMillis(issues.fields.customfield_11200.ongoingCycle.remainingTime.millis)
except:
    tdsla_ongoing = np.nan

try:
    querysla_comp = convertMillis(issues.fields.customfield_10142.completedCycles[0].remainingTime.millis)
except:
    querysla_comp = np.nan
try:
    querysla_ongoing = convertMillis(issues.fields.customfield_10142.ongoingCycle.remainingTime.millis)
except:
    querysla_ongoing = np.nan

try:
    recsla_comp = convertMillis(issues.fields.customfield_15600.completedCycles[0].remainingTime.millis)
except:
    recsla_comp = np.nan
try:
    recsla_ongoing = convertMillis(issues.fields.customfield_15600.ongoingCycle.remainingTime.millis)
except:
    recsla_ongoing = np.nan

try:
    reportsla_comp = convertMillis(issues.fields.customfield_15601.completedCycles[0].remainingTime.millis)
except:
    reportsla_comp = np.nan
try:
    reportsla_ongoing = convertMillis(issues.fields.customfield_15601.ongoingCycle.remainingTime.millis)
except:
    reportsla_ongoing = np.nan

Мне было бы удобно сделать что-то вроде взятия всех пользовательских полей, поместить их в один список, а затем выполнить операцию над функцией, например:

field_list = ['customfield_10705','customfield_10136','customfield_10713','customfield_10711','customfield_10140','customfield_10213','customfield_10144','customfield_10134','customfield_11200','customfield_10142','customfield_15600','customfield_15601']


  def get_jira_hours(field):
        try:
            newaccsla_comp = convertMillis(issues.fields.field.completedCycles[0].remainingTime.millis)
        except:
            newaccsla_comp = np.nan
        try:
            newaccsla_ongoing = convertMillis(issues.fields.field.ongoingCycle.remainingTime.millis)
        except:
            newaccsla_ongoing = np.nan

for field in field_list:
    get_jira_hours(field)

Однако есть три переменные, которыесвязаны с каждым вызовом функции, который мне нужно перебрать - customfield_10705 и имя для сохранения каждой попытки / за исключением слишком newaccsla_comp и newaccsla_ongoing.

Вот переменные по порядку ... т.е.field_list[0] связан с name_list[0]

field_list = ['customfield_10705','customfield_10136','customfield_10713','customfield_10711','customfield_10140','customfield_10213','customfield_10144','customfield_10134','customfield_11200','customfield_10142','customfield_15600','customfield_15601']

name_list = ['newaccsla','paymentssla','modifysla','MFsla','closeaccsla','casla','at','modfeesla','tdsla','querysla','recsla','reportssla']

Лучший способ перебрать их?Спасибо.

1 Ответ

0 голосов
/ 31 мая 2018

Во-первых, вы можете превратить каждый из этих четырехстрочных блоков в однострочный, если вы просто отредактируете свою функцию convertMillis, чтобы она возвращала np.nan вместо повышения, или, если вы не можете этого сделать, обернитефункция в другом:

def convertMillisOrNan(millis):
    try:
        return convertMillis(millis)
    except:
        return np.nan

newaccsla_comp = convertMillisOrNan(issues.fields.customfield_10705.completedCycles[0].remainingTime.millis)
newaccsla_ongoing = convertMillisOrNan(issues.fields.customfield_10705.ongoingCycle.remainingTime.millis)
# etc.

Или, может быть, исключение, которое вы пытаетесь обработать, идет немного дальше.Вы всегда звоните convertMillis на <something>.remainingTime.millis.Что если, скажем, поле всегда существует и всегда имеет ongoingCycle, но оно не всегда имеет атрибут remainingTime?Затем вы можете вставить эту часть в try:, а также упростить вещи одновременно:

def convertCycle(cycle):
    try:
        return convertMillis(cycle.remainingTime.millis)
    except:
        return np.nan
newaccsla_comp = convertCycle(issues.fields.customfield_10705.completedCycles[0])
newaccsla_ongoing = convertCycle(issues.fields.customfield_10705.ongoingCycle)

Если исключение поднимается еще выше, например, если поле не 't всегда имеет ongoingCycle - очевидно, вам нужно поместить больше выражения в блок try:;Я действительно просто догадываюсь здесь о том, что вы пытаетесь с этим справиться except:.


И, хотя у вас это получается, вы действительно хотите получить except:?Это будет обрабатывать любое исключение, а не только AttributeError или ValueError или любое другое исключение, которое вы ожидали.


Между тем, ваш существующий рефактор jira_hours не работает, потому что вы можетепросто используйте .field, когда field является переменной, содержащей строку.Один из способов решения этой проблемы:

def get_jira_hours(field):
    comp = convertCycle(field.completedCycles[0])
    ongoing = convertCycle(field.ongoingCycle)
    return comp, ongoing

newaccsla_comp, newaccsla_ongoing = get_jira_hours(issues.fields.customfield_10705)
paymentssla_comp, paymentssla_ongoing = get_jira_hours(issues.fields.customfield_10136)
# etc.

Другой способ решения проблемы - с помощью getattr, что я покажу ниже.


Но вы можете сделать еще лучше.Вы действительно нуждаетесь в том, чтобы все они были независимыми переменными, а не, скажем, элементами в поле?

fieldmap = {
    'newaccsla': 'customfield_10136',
    'paymentssla': 'customfield_10705',
    # etc.
}

values = {}
for fieldname, customfieldname in fieldmap.items():
    field = getattr(issues.fields, customfieldname)
    comp, ongoing = get_jira_hours(field)
    values[f'{fieldname}_comp'] = comp
    values[f'{fieldname}_ongoing'] = ongoing

Теперь вместо использования newaccsla_comp вы должны использовать values['newaccsla_comp'].Но я подозреваю, что ваш код на самом деле будет делать много кода, где вы копируете и вставляете одну и ту же вещь для каждой переменной, которую вы можете заменить кодом, который просто зацикливается на dict.

Но если вы действительнонужно, чтобы они были независимыми переменными - что, опять же, вы, вероятно, делаете - вы можете сделать то же самое, просто используя globals() или locals() вместо values.

С другой стороны, есливы будете повторяться над парой значений comp / current, просто сохраните пары в файле dict: values[fieldname] = comp, ongoing.

Кроме того, поскольку все имена пользовательских полей кажутся customfield_NNNNN,Вы можете еще больше упростить вещи, сопоставив 'newaccsla': 10136 и т. д., а затем выполнив getattr(issue.fields, f'customfield_{customfield}').

...