我在具有1GB RAM的Mac Mini上使用Python 2.6。我想阅读一个巨大的文本文件
$ ls -l links.csv; file links.csv; tail links.csv
-rw-r--r-- 1 user user 469904280 30 Nov 22:42 links.csv
links.csv: ASCII text, with CRLF line terminators
4757187,59883
4757187,99822
4757187,66546
4757187,638452
4757187,4627959
4757187,312826
4757187,6143
4757187,6141
4757187,3081726
4757187,58197
因此,文件中的每一行都由两个逗号分隔的整数值组成的元组。我想阅读整个文件,并根据第二列对其进行排序。我知道,我可以进行排序而无需将整个文件读入内存。但我认为对于500MB的文件,由于我有1GB的可用空间,因此仍应该可以在内存中进行处理。
但是,当我尝试读取文件时,Python似乎分配了比磁盘上的文件所需更多的内存。因此,即使有1GB的RAM,我也无法将500MB的文件读入内存。我用于读取文件和打印一些有关内存消耗信息的Python代码是:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
infile=open("links.csv", "r")
edges=[]
count=0
#count the total number of lines in the file
for line in infile:
count=count+1
total=count
print "Total number of lines: ",total
infile.seek(0)
count=0
for line in infile:
edge=tuple(map(int,line.strip().split(",")))
edges.append(edge)
count=count+1
# for every million lines print memory consumption
if count%1000000==0:
print "Position: ", edge
print "Read ",float(count)/float(total)*100,"%."
mem=sys.getsizeof(edges)
for edge in edges:
mem=mem+sys.getsizeof(edge)
for node in edge:
mem=mem+sys.getsizeof(node)
print "Memory (Bytes): ", mem
我得到的输出是:
Total number of lines: 30609720
Position: (9745, 2994)
Read 3.26693612356 %.
Memory (Bytes): 64348736
Position: (38857, 103574)
Read 6.53387224712 %.
Memory (Bytes): 128816320
Position: (83609, 63498)
Read 9.80080837067 %.
Memory (Bytes): 192553000
Position: (139692, 1078610)
Read 13.0677444942 %.
Memory (Bytes): 257873392
Position: (205067, 153705)
Read 16.3346806178 %.
Memory (Bytes): 320107588
Position: (283371, 253064)
Read 19.6016167413 %.
Memory (Bytes): 385448716
Position: (354601, 377328)
Read 22.8685528649 %.
Memory (Bytes): 448629828
Position: (441109, 3024112)
Read 26.1354889885 %.
Memory (Bytes): 512208580
在仅读取500MB文件的25%之后,Python消耗了500MB。因此,似乎将文件的内容存储为int元组的列表并不是很节省内存。是否有更好的方法可以将500MB文件读入1GB内存?
此页面上有一个用于对大于RAM的文件进行排序的方法,尽管您必须针对涉及CSV格式数据的情况进行调整。那里也有指向其他资源的链接。
编辑: 确实,磁盘上的文件不是“大于RAM”,但是内存中的表示形式很容易变得比 可用RAM
大得多。一方面,您自己的程序无法获得全部1GB(操作系统开销等)。另外,即使您以最紧凑的形式将其存储为纯Python(两个整数列表,假设使用32位计算机等),对于这30M对整数,您仍将使用934MB。
使用numpy,您也可以完成这项工作,仅使用约250MB。以这种方式加载并不是特别快,因为您必须计算行数并预分配数组,但是考虑到它在内存中,它可能是最快的实际排序:
import time
import numpy as np
import csv
start = time.time()
def elapsed():
return time.time() - start
# count data rows, to preallocate array
f = open('links.csv', 'rb')
def count(f):
while 1:
block = f.read(65536)
if not block:
break
yield block.count(',')
linecount = sum(count(f))
print '\n%.3fs: file has %s rows' % (elapsed(), linecount)
# pre-allocate array and load data into array
m = np.zeros(linecount, dtype=[('a', np.uint32), ('b', np.uint32)])
f.seek(0)
f = csv.reader(open('links.csv', 'rb'))
for i, row in enumerate(f):
m[i] = int(row[0]), int(row[1])
print '%.3fs: loaded' % elapsed()
# sort in-place
m.sort(order='b')
print '%.3fs: sorted' % elapsed()
在我的机器上输出的示例文件类似于您显示的内容:
6.139s: file has 33253213 lines
238.130s: read into memory
517.669s: sorted
numpy中的默认值为Quicksort。ndarray.sort()例程(就地排序)也可以采用关键字参数kind="mergesort"
,kind="heapsort"
但是似乎这两个方法均不能在Record
Array
上进行排序,顺便说一句,我用它作为唯一的排序方法列 一起使用
,而不是默认值,后者将对它们进行独立排序(完全弄乱了您的数据)。
问题内容: 我目前正在尝试从Python 2.7中的.csv文件中读取数据,该文件最多包含100万行和200列(文件范围从100mb到1.6gb)。对于少于300,000行的文件,我可以(非常缓慢地)执行此操作,但是一旦超过该行,就会出现内存错误。我的代码如下所示: 在getstuff函数中使用else子句的原因是,所有符合条件的元素都将一起列在csv文件中,因此,经过它们以节省时间时,我离开了循
问题内容: 我目前正在尝试从Python 2.7中的.csv文件中读取数据,该文件最多包含100万行和200列(文件范围从100mb到1.6gb)。对于少于300,000行的文件,我可以(非常缓慢地)执行此操作,但是一旦超过该行,就会出现内存错误。我的代码如下所示: 在getstuff函数中使用else子句的原因是,所有符合条件的元素都将一起列在csv文件中,因此当我经过它们时,为了节省时间,我离
问题内容: 我有一个很大的csv文件,因此无法将它们全部读入内存。我只想阅读和处理其中的几行内容。所以我正在Pandas中寻找一个可以处理此任务的函数,基本的python可以很好地处理此任务: 但是,如果我在熊猫中这样做,我总是会读第一行: 我正在寻找一些更简单的方法来处理熊猫中的这项任务。例如,如果我想读取1000到2000的行。如何快速执行此操作? 我想使用熊猫,因为我想将数据读入数据框。 问
问题内容: 我有一个巨大的XML文件(15 GB)。我想将XML文件中的“文本”标签转换为单个页面。 样本XML文件: 我最初使用DOM解析器,但它使JAVA OUT OF MEMORY(Valid)不足。现在,我已经使用STAX编写了JAVA代码。它运作良好,但是性能确实很慢。 这是我编写的代码: 这段代码运行良好。(忽略任何小错误)。根据我的理解,XMLStreamConstants.CHAR
问题内容: 我需要逐行读取一个大文件。可以说该文件的大小超过5GB,我需要读取每一行,但是显然我不想使用它,因为它将在内存中创建一个非常大的列表。 下面的代码在这种情况下将如何工作?自身是否一一读取到内存中?是否需要生成器表达式? 另外,与命令一样,我该怎么做才能以相反的顺序阅读? 问题答案: 我提供此答案是因为Keith的提示虽然简洁,但并未明确关闭文件
问题内容: 我编写了一个PHP脚本,该脚本贯穿文本文件(实际上是imdb的“列表”文件)并将其存储在本地MySQL数据库中。 由于这些列表文件最大为200MB,因此需要花费大量时间。默认情况下,PHP 设置为30秒。 我将此值设置为300只是为了尝试是否可行。例如,我的“ movies.list”文件约为80MB,并使用此脚本运行了300秒,在数据库中创建了约25000行。这行不通,因为我什至没有