如何偶尔为长时间运行的Python列表推导提供反馈
如果你在Python中有一个运行时间很长的列表推导式,比如:
from itertools import combinations
print [w for w in (''.join(c) for c in combinations(words, 2)) if sorted(w) == letters]
这里的words是一个包含20万个单词的列表,而letters是一个字母的列表;有没有办法偶尔打印出到目前为止处理了多少个单词,或者以其他形式显示进度报告呢?
3 个回答
0
为了让内容更完整,这里有一个小技巧,你可以用来定期打印出你的列表推导式的状态。比如说,当你在生成只包含奇数的列表时,如果想每处理一万条数据就打印一条消息,可以这样做:
test = [x for x in range(100000)
if x % 2 or (x % 10000 == 0 and print("Processed: " + str(x)) is None and x % 2)]
不过要注意,这其实算是一种小窍门(而且因为增加了额外的条件判断,可能并不会提高性能)。所以如果你需要定期打印信息,我建议你把循环拆开,采用更合理的方式来处理这个“报告”逻辑。
1
这是一个生成器,它可以把进度记录到日志里。
def log_every(seq, every):
for i, x in enumerate(seq):
if (i + 1) % every == 0:
logging.info('Generated %d', i)
yield x
你可以这样使用它:
for c in log_every(combinations(words, 2), 2000):
...
1
你需要把它转换成一个普通的循环,不要试着把一个有副作用的函数混在里面:
from itertools import combinations
result = []
count = 0
for w in (''.join(c) for c in combinations(words, 2)):
if sorted(w) == letters:
result.append(w)
count += 1
if count % 2000 == 0:
print 'Progress: {0} matching combinations found'.format(count)
print result
或者,如果你想记录测试过的组合,可以把计数放在if
之前:
from itertools import combinations
result = []
count = 0
for w in (''.join(c) for c in combinations(words, 2)):
count += 1
if count % 2000 == 0:
print 'Progress: {0} combinations scanned'.format(count)
if sorted(w) == letters:
result.append(w)
print result