【问题标题】:Tracking how many elements processed in generator跟踪生成器中处理了多少元素
【发布时间】:2014-06-22 00:57:59
【问题描述】:

我在使用 python 生成器处理文件中的文档时遇到问题。我需要处理的文件数量事先不知道。每个文件都包含消耗大量内存的记录。因此,生成器用于处理记录。这是我正在处理的代码的摘要:

def process_all_records(files):
   for f in files:
      fd = open(f,'r')
      recs = read_records(fd)
      recs_p = (process_records(r) for r in recs)
      write_records(recs_p)

我的process_records 函数检查每条记录的内容,只返回具有特定发件人的记录。我的问题如下:我想计算read_records 返回的元素数量。我一直在使用列表跟踪 process_records 函数中的记录数:

def process_records(r):
    if r.sender('sender_of_interest'):
       records_list.append(1)
    else:
       records_list.append(0)
    ...

这种方法的问题是records_list 可以根据输入无限制地增长。我希望能够在 records_list 增长到某个点后使用它的内容,然后重新启动该过程。例如,处理完 20 条记录后,我想找出有多少条记录来自'sender_of_interest',有多少条记录来自其他来源并清空列表。我可以在不使用锁的情况下执行此操作吗?

【问题讨论】:

  • 为什么不使用整数计数器而不是列表?
  • 好像你可以让read_records()检查sender,只返回那些感兴趣的。在这种情况下,您分配给recs 的值返回的长度将是生成器将处理的数字。
  • 是的,我可以。但我更喜欢你使用类的想法。我正在使用的代码是由其他人编写的,我不希望出于我的目的重构此代码。谢谢。

标签: python python-3.x generator counting


【解决方案1】:

这是简单的方法。为什么这么简单的东西对你不起作用?

seen=0
matched=0

def process_records(r):
    seen = seen + 1
    if r.sender('sender_of_interest'):
       matched = match + 1
       records_list.append(1)
    else:
       records_list.append(0)

    if seen > 1000 or someOtherTimeBasedCriteria:
       print "%d of %d total records had the sender of interest" % (matched, seen)
       seen = 0
       matched = 0

如果您能够关闭消息流并重新打开它们,您可能需要一个总可见变量,这样如果您必须关闭该流并稍后重新打开它,您可以转到您处理并在那里提取的最后一条记录。

在此代码中,“someOtherTimeBasedCriteria”可能是一个时间戳。您可以在开始处理时以毫秒为单位获取当前时间,然后如果当前时间超过 20,000 毫秒(20 秒),则重置已看到/匹配的计数器。

【讨论】:

    【解决方案2】:

    您可以使您的生成器成为一个类,其属性包含它已处理的记录数的计数。像这样的:

    class RecordProcessor(object):
        def __init__(self, recs):
            self.recs = recs
            self.processed_rec_count = 0
        def __call__(self):
            for r in self.recs:
                if r.sender('sender_of_interest'):
                   self.processed_rec_count += 1
                   # process record r...
                   yield r  # processed record
    
    def process_all_records(files):
        for f in files:
            fd = open(f,'r')
            recs_p = RecordProcessor(read_records(fd))
            write_records(recs_p)
            print 'records processed:', recs_p.processed_rec_count
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多