简体   繁体   中英

nested list comprehension using intermediate result

I am trying to grok the output of a function which doesn't have the courtesy of setting a result code. I can tell it failed by the "error:" string which is mixed into the stderr stream, often in the middle of a different conversion status message.

I have the following list comprehension which works, but scans for the "error:" string twice. Since it is only rescanning the actual error lines, it works fine, but it annoys me I can't figure out how to use a single scan. Here's the working code:

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

The obvious (and wrong) way to simplify is to save the "find" result

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

However, I get "UnboundLocalError: local variable 'e' referenced before assignment". Blindly reversing the 'for's in the comprehension also fails. How is this done?

THanks. Kent

You can place the check for 'error' inside a generator expression:

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

What you did was to create a nested comprehension and, by using the e variable before the second loop, you got the UnboundLocalError

BTW, you can also use regex and avoid this comprehension:

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

No need to split lines also.

for the complete error (with the error: part) this works:

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

Use a generator with a normal loop to perform this sort of task which needs state:

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

If you need this as a list, just do list(errsplit(err)) .

List comprehensions's aren't really intended to deal with stored state, and attempts to use stored state in them can get clunky.

That said, note that a regex might better, as suggested by @JBernardo.

I've tried JBernardo's solutions but what really worked for me was:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM