2012-06-26 3 views
2

Я пытаюсь получить вывод функции, которая не имеет права устанавливать код результата. Я могу сказать, что это произошло из-за строки «error:», которая смешивается с потоком stderr, часто в середине другого сообщения о статусе преобразования.Вложенное понимание списка с использованием промежуточного результата

У меня есть следующее понимание списка, которое работает, но дважды проверяет строку «error:». Поскольку это только повторное сканирование фактических строк ошибок, оно работает нормально, но меня это раздражает, я не могу понять, как использовать одно сканирование. Вот рабочий код:

errors = [e[e.find('error:'):] for e in err.splitlines() if 'error:' in e] 

Очевидная (и неправильно) способ упростить это, чтобы сохранить «найти» результат

errors = [e[i:] for i in e.find('error:') if i != -1 for e in err.splitlines()] 

Однако, я получаю «UnboundLocalError: локальная переменная„е“, на который ссылается, прежде назначение». Слепое обращение вспять «за» в понимании также терпит неудачу. Как это делается?

Спасибо. Kent

+0

Предоставить образец? – MattH

+2

сначала. почему не регулярное для цикла с чем-то, что выглядит так мило, как это? –

+0

'errors = filter (None, (e.split ('error:', 1) + [None]) [1] для e в err.splitlines())' – astynax

ответ

3

Вы можете поместить чек на 'error' внутри выражения генератора:

[e[i:] for i,e in 
((e.find('error:'),e) for e in err.splitlines()) 
if i != -1] 

То, что вы сделали, чтобы создать вложенное понимание и, используя переменную e до второго цикла, вы получили UnboundLocalError

Кстати, вы также можете использовать регулярные выражения и избежать этого понимания:

re.findall('error:(.*)', err) 

Нет необходимости Spl это также линии.

для полной погрешности (с error: части) это работает:

re.findall('error:.*', err) 
+0

Это работает, но кажется менее легким для чтения, чем просто записывая одну функцию генератора. – Marcin

+0

@Marcin Я просто поправлял понимание. Реальный ответ - это простое регулярное выражение, которое лучше генератора. – JBernardo

+0

Я пробовал первое решение, и в моем примере он не работает. Получил только подстроки последней строки вместо реальных сообщений об ошибках ... Я добавил исправленную версию, поскольку комментарии не принимают код ... – bcelary

2

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

def errsplit(err): 
    for e in err.splitlines(): 
     errindex = e.find('error:') 
     if errindex > -1: yield e[errindex:] 

Если вы нужно это как список, просто сделайте list(errsplit(err)).

Рецепты списков на самом деле не предназначены для работы с сохраненным состоянием, а попытки использования сохраненного состояния в них могут стать неуклюжими.

При этом обратите внимание, что регулярное выражение может быть лучше, как это было предложено @JBernardo.

+2

+1 для удобства чтения – bcelary

0

Я попытался решения JBernardo, но что на самом деле работал для меня было:

[errstr[i:] for i,errstr in 
((e.find('error:'), e) for e in err.splitlines()) 
if i != -1] 
+1

Зачем придерживаться этого oneliner, который вы не можете поместить в одну строку, и который сложно читать? – Marcin

+0

Я только исправил другую версию, представленную JBernardo, которая на самом деле не работала;) – bcelary

Смежные вопросы