Python 如何克服顺序追加文件时的内存问题

Python 如何克服顺序追加文件时的内存问题,python,memory,python-2.7,buffer,stringio,Python,Memory,Python 2.7,Buffer,Stringio,我正在运行下面的脚本,以便通过几个月和几年的循环将文件附加到另一个文件中。如果文件存在,我刚刚使用一个更大的数据集对其进行了测试,我希望输出文件的大小大约为600mb。但是,我遇到了内存问题。首先,遇到内存问题(我的电脑有8 gb ram)是正常的吗?我不确定我是如何消耗所有这些内存空间的 我正在运行的代码 内存错误是因为在写入数据之前将所有数据存储在缓冲区中。考虑使用类似于直接从一个打开的文件对象复制到另一个文件对象的方法,这样只会一次缓冲少量的数据。你也可以一行一行地做,效果差不多 更新 使

我正在运行下面的脚本,以便通过几个月和几年的循环将文件附加到另一个文件中。如果文件存在,我刚刚使用一个更大的数据集对其进行了测试,我希望输出文件的大小大约为600mb。但是,我遇到了内存问题。首先,遇到内存问题(我的电脑有8 gb ram)是正常的吗?我不确定我是如何消耗所有这些内存空间的

我正在运行的代码
内存错误是因为在写入数据之前将所有数据存储在缓冲区中。考虑使用类似于直接从一个打开的文件对象复制到另一个文件对象的方法,这样只会一次缓冲少量的数据。你也可以一行一行地做,效果差不多

更新

使用
copyfileobj
应该比逐行写入文件快得多。下面是一个如何使用
copyfileobj
的示例。此代码打开两个文件,如果
skip_first_line
为真,则跳过输入文件的第一行,然后将该文件的其余部分复制到输出文件

skip_first_line = True

with open('FullMergedData.csv', 'a') as output_csv:
    with open(csv_filename, 'rb') as current_csv:
        if skip_first_line:
            current_csv.readline()
        shutil.copyfileobj(current_csv, output_csv)

请注意,如果使用的是
copyfileobj
,则需要使用
current\u csv.readline()
而不是
next(current\u csv)
。这是因为在文件对象上迭代会缓冲文件的一部分,这通常非常有用,但在这种情况下,您不希望这样

存储的\u数据中
,您试图存储整个文件,由于文件太大,因此会出现显示的错误

一种解决方案是每行写入文件。它的内存效率要高得多,因为您只在缓冲区中存储一行数据,而不是整个600 MB

简而言之,结构可以是这样的:

with open('FullMergedData.csv', 'a') as output_csv: #this will append  
# the result to the file.
    with open(csv_filename, 'rb') as current_csv:
        for line in current_csv:   #loop through the lines
            if first_run != False:
                next(current_csv)
                first_run = True #After the first line,
                #you should immidiately change first_run to true.
            output_csv.writelines(line)  #write it per line

应该能解决你的问题。希望这有帮助

您是否可以直接写入csv,而不是将数据存储在内存中然后再写入?@SethMMorton是的,但我正在尝试避免过多的文件写入。上面针对较小数据文件的脚本是即时的,因为其他涉及多次读取和写入的方法被证明很慢。感谢您的回复,我不知道如何用我以前问题中的想法更新我的代码,因此我在这里输入了完整的代码。我在我的问题中添加了回溯。很多感谢,你从未将
first_run
更改为True。此外,如果这解决了你的问题,请进行投票,并接受:)嘿@alKid虽然这确实修复了回溯,但代码没有正常工作,这段代码在不同的文件中循环时不记得最后一个文件,也就是说,当它循环到下一个月的文件时,它会覆盖它。是的,它也不是很快。最初的代码是即时的,这将需要几分钟的时间来运行(不理想),我在文档中查看了它,但找不到合适的示例。您能提供一个如何正确使用它的小示例吗?
copyfileobj
用于复制整个文件,如果要删除第一行,您应该跳过。@aIKid copyfileobj从文件指针的当前位置开始复制。这意味着您只需读取您想要跳过的文件,然后开始复制。当然,这意味着您需要注意任何类型的缓冲。
Traceback (most recent call last):
  File "C:\FullMerger.py", line 22, in <module>
    output_csv.writeline(line)
AttributeError: 'file' object has no attribute 'writeline'
Traceback (most recent call last):
  File "C:\FullMerger.py", line 19, in <module>
    next(current_csv)
StopIteration
skip_first_line = True

with open('FullMergedData.csv', 'a') as output_csv:
    with open(csv_filename, 'rb') as current_csv:
        if skip_first_line:
            current_csv.readline()
        shutil.copyfileobj(current_csv, output_csv)
with open('FullMergedData.csv', 'a') as output_csv: #this will append  
# the result to the file.
    with open(csv_filename, 'rb') as current_csv:
        for line in current_csv:   #loop through the lines
            if first_run != False:
                next(current_csv)
                first_run = True #After the first line,
                #you should immidiately change first_run to true.
            output_csv.writelines(line)  #write it per line