如何在python中输入一个1000万行的大文件?
我想用python分析一个有1000万用户和密码的文件。文件为文本格式。以下是一些数据行:如何在python中输入一个1000万行的大文件?,python,Python,我想用python分析一个有1000万用户和密码的文件。文件为文本格式。以下是一些数据行: 0000 00000000 0000 00001 0000 00001111 0000 000099 0000 00009999 0000 0000w 0000 5927499 0000 634252 0000 6911703 0000 701068 在python中,我使用以下代码读取该文件: f=open('10-million-combo
0000 00000000
0000 00001
0000 00001111
0000 000099
0000 00009999
0000 0000w
0000 5927499
0000 634252
0000 6911703
0000 701068
在python中,我使用以下代码读取该文件:
f=open('10-million-combos.txt','r')
a=[]
for line in f.readlines():
a.append(line)
上面的代码需要几秒钟才能运行。保存在列表中的数据如下所示:
>>>a[0:2]
['0000\t00000000\n', '0000\t00001\n']
要提取我使用的用户和密码,请执行以下操作:
b=[]
for i in a:
b.append(i.split('\t'))
问题是,上面的代码在很长一段时间后遇到内存错误,我无法区分用户和密码
您对解决方案有什么建议吗?只需迭代每一行,然后根据制表符进行拆分,然后将返回的列表附加到已声明的列表
l
l = []
with open('10-million-combos.txt','r') as f:
for line in f:
l.append(line.strip().split('\t'))
只需迭代每一行,然后根据制表符进行拆分,然后将返回的列表附加到已声明的列表
l
l = []
with open('10-million-combos.txt','r') as f:
for line in f:
l.append(line.strip().split('\t'))
同时读取和拆分可减少所需的内存:
b = []
with open('10-million-combos.txt','r') as inp:
for line in inp:
b.append(line.strip().split('\t',1))
同时读取和拆分可减少所需的内存:
b = []
with open('10-million-combos.txt','r') as inp:
for line in inp:
b.append(line.strip().split('\t',1))
如果文件是tsv(看起来是这样),则始终可以使用pythons
csv
module
import csv
with open('10-million-combos.txt','r') as f:
reader = csv.reader(f, delimiter="\t")
for line in reader:
user_name = line[0]
password = line[1]
....
这应该允许您迭代地解析文件并执行需要执行的操作,而无需将所有行保存到一个大列表中。如果文件是tsv(看起来是),您可以始终使用pythons
csv
模块
import csv
with open('10-million-combos.txt','r') as f:
reader = csv.reader(f, delimiter="\t")
for line in reader:
user_name = line[0]
password = line[1]
....
这应该允许您迭代地解析文件并执行需要执行的操作,而无需将所有行保存到一个大列表中。问题在于您正在将每一行读入Python列表中。档案有多大?这就是你在记忆中投入的量 在同一步骤中进行阅读和分析,以便Python可以进行垃圾收集 当您转到分析部分时,您可能希望签出,这是一个用于数据分析的库 这些建议您添加到列表中的其他答案在内存使用方面也会遇到同样的问题。诀窍是不要建立一个列表,以增量方式进行分析,这样就不需要在内存中存储1000万行 如果要按照注释中的说明递增总计,并且绝对必须将其存储在内存中,则可以将值作为键存储在字典中并递增计数 这仍然会导致内存使用,因此如果它仍然崩溃,您可以选择:
- 每次迭代都会将其持久化到磁盘(写入另一个文件)。然后,您可以读取每个文件并获取总数,并通过一个变量计算出哪一个文件的总数最高。这会很慢,但会以内存使用率换取磁盘使用率
- 使用修改过的二叉树来防止将任何位存储两次,并添加一个“times”变量,您可以将其增量添加到节点: ab abc abc A{times:0}->B{times:1}->C{times:2}
- 每次迭代都会将其持久化到磁盘(写入另一个文件)。然后,您可以读取每个文件并获取总数,并通过一个变量计算出哪一个文件的总数最高。这会很慢,但会以内存使用率换取磁盘使用率
- 使用修改过的二叉树来防止将任何位存储两次,并添加一个“times”变量,您可以将其增量添加到节点: ab abc abc A{times:0}->B{times:1}->C{times:2}
除了其他答案之外,您还可以考虑使用生成器,它只在您实际需要数据时加载数据(想想惰性评估):
坦白地说,我很惊讶你没有足够的内存将185MB的文件读入内存,即使你实际上创建了它的两个副本。当今大多数现代系统都有GB的内存可供使用 这里只创建了一个元组列表,它比代码中的列表要小 假设成功,有一些示例可以在数据集中找到最常见的用户id和密码
from collections import Counter # dictionary subclass
records = []
with open('10-million-combos.txt', 'rU') as inf:
for line in (line.strip() for line in inf):
records.append(tuple(line.split('\t', 1)))
# display some of the test data read
print('Data:')
for rec in records[0:10]:
print(rec)
print('')
# find most common user id
counter = Counter((rec[0] for rec in records))
print('most common user id: {}'.format(counter.most_common(1)[0][0]))
# find most common password
counter = Counter((rec[1] for rec in records))
print('most common password: {}'.format(counter.most_common(1)[0][0]))
输出:
数据:
('0000', '00000000')
('0002', '00001')
('0002', '00001111')
('0003', '000099')
('0004', '00009999')
('0006', '000099')
('0006', '5927499')
('0006', '634252')
('0008', '6911703')
('0009', '701068')
最常见的用户id:0006
最常用密码:000099
注意:我更改了您问题中的示例数据,因此会有一些重复的用户id和密码。坦率地说,我很惊讶您没有足够的内存将185MB的文件读入内存,即使您实际上创建了两个副本。当今大多数现代系统都有GB的内存可供使用 这里只创建了一个元组列表,它比代码中的列表要小 假设成功,有一些示例可以在数据集中找到最常见的用户id和密码
from collections import Counter # dictionary subclass
records = []
with open('10-million-combos.txt', 'rU') as inf:
for line in (line.strip() for line in inf):
records.append(tuple(line.split('\t', 1)))
# display some of the test data read
print('Data:')
for rec in records[0:10]:
print(rec)
print('')
# find most common user id
counter = Counter((rec[0] for rec in records))
print('most common user id: {}'.format(counter.most_common(1)[0][0]))
# find most common password
counter = Counter((rec[1] for rec in records))
print('most common password: {}'.format(counter.most_common(1)[0][0]))
输出:
数据:
('0000', '00000000')
('0002', '00001')
('0002', '00001111')
('0003', '000099')
('0004', '00009999')
('0006', '000099')
('0006', '5927499')
('0006', '634252')
('0008', '6911703')
('0009', '701068')
最常见的用户id:0006
最常见的passwo