2

我有一个产生“事件”的迭代器/生成器。事件由名称、时间戳和值组成。我想将它们存储在 NumPy 数组中。这是在_LoadTriples()

def _LoadTriples(abortEvt, count=[1]):
    it = _YieldTriples()
    while True:
        if abortEvt.is_set():
            it.close()
            break
        t0 = time.time()
        self.allEvents.append(np.fromiter(it,
                                      dtype=[('sigNameIdx', 'i'),
                                             ('time', 'f'),
                                             ('value', 'f8')],
                                      count=count[-1]))
        dur = time.time() - t0
        if dur < 0.2:
            count.append(count[-1]*2)
        elif dur > 0.4 and count[-1] != 1:
            count.append(count[-1]/2)
        else:
            count.append(count[-1])

_YieldTriples是生成器,abortEvt是告诉我用户何时中止迭代的事件。self.allEvents是一个空列表。在这里,我想在 NumPy 数组中附加 Triples(name, timestamp, value).它是一个数组列表,因为我希望有可能中断迭代并且我不能中断numpy.fromiter。所以每大约 0.3 秒我可以停止迭代。

这一切都很好。但是,在一个示例中,Python 很快就为列表使用了 300MB 内存!当我停止迭代时,我的列表最多只需要 10 MB,这取决于我何时停止它,但是在使用了几次对self.allEvents.append(np.fromiter(...))300MB 的调用之后,我完全不知道为什么。

此外,在我停止整个程序之前,这个内存不会被释放,即使我self.allEvents在调用该函数后直接删除。一定有一些参考资料阻止我发布它。有什么方法可以查看哪些对象引用了列表?

还要提到一件事:该函数被称为 new threading.Thread,但主线程等待它......

编辑:我没有提到,一旦使用了 300MB,随着列表的增长,不再分配内存。似乎列表在一些附加后保留了这个内存。

4

1 回答 1

2

你应该试试:

def _LoadTriples(abortEvt, count=None):
    if count is None:
        count = [1]
    ...

可变的默认参数会很快导致问题。

于 2013-06-20T17:30:25.810 回答