Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python csv.DictReader的内存使用问题_Python_Memory Management - Fatal编程技术网

Python csv.DictReader的内存使用问题

Python csv.DictReader的内存使用问题,python,memory-management,Python,Memory Management,我在Python3中使用它来处理一个非常大的CSV文件。我发现了一个奇怪的内存使用问题 代码是这样的 import os import csv import psutil # require pip install # the real CSV file is replaced with a call to this function def generate_rows(): for k in range(400000): yield ','.join(str(i *

我在Python3中使用它来处理一个非常大的CSV文件。我发现了一个奇怪的内存使用问题

代码是这样的

import os
import csv
import psutil # require pip install

# the real CSV file is replaced with a call to this function
def generate_rows():
    for k in range(400000):
        yield ','.join(str(i * 10 + k) for i in range(35))


def memory_test():
    proc = psutil.Process(os.getpid())
    print('BEGIN', proc.memory_info().rss)

    fieldnames = ['field_' + str(i) for i in range(35)]
    reader = csv.DictReader(generate_rows(), fieldnames)
    result = []
    for row in reader:
        result.append(row)

    print('  END', proc.memory_info().rss)
    return result


if __name__ == '__main__':
    memory_test()
在上面的代码中,程序将
打印
内存使用情况(需要安装
psutil
),结果如下

BEGIN 12623872
  END 2006462464
BEGIN 12726272
  END 1289912320
您可以看到,在进程结束时,它将占用近2GB的内存

但是如果我复制每一行,内存使用就会降低

def memory_test():
    proc = psutil.Process(os.getpid())
    print('BEGIN', proc.memory_info().rss)

    fieldnames = ['field_' + str(i) for i in range(35)]
    reader = csv.DictReader(generate_rows(), fieldnames)
    result = []
    for row in reader:
        # MAKE A COPY
        row_copy = {key: value for key, value in row.items()}
        result.append(row_copy)

    print('  END', proc.memory_info().rss)
    return result
结果是

BEGIN 12623872
  END 2006462464
BEGIN 12726272
  END 1289912320
它只需要大约1.29G内存,要少得多

(我在64位Ubuntu上测试了代码,得到了这些结果。)

为什么会发生这种情况?从
读写器
复制行是否合适?

如果
打印(行)
,您会发现
是一个
有序的读写器
。在第二个示例中,您将此
OrderedDict
替换为正常的
dict
。他们是不同的

在第二个示例中,使用
orderedict
可以获得相同的结果:

for row in reader:
    from collections import OrderedDict
    # MAKE A COPY
    row_copy = OrderedDict({key: value for key, value in row.items()})
    result.append(row_copy)

顺便说一句,如果你想让这段代码更有效率,你可以编写
result=list(csv.DictReader(generate_rows(),fieldnames))
——这样可以避免多次追加到列表,这会导致CPython不断重新分配内存以增加列表的大小。@elias确实如此。我只是保留了代码的外观,因为在实际代码中对
对象有一些更改。如果可能的话,将这些更改移动到函数中并将其转换为列表理解
result=[change_row(row)for row in csv.DictReader(…)]