在Python中将大文件(25k条目)加载到dict中是很慢的?

she*_*ngy 5 python io performance dictionary

我有一个大约25000行的文件,它是一个s19格式的文件.

每一行如下:S214 780010 00802000000010000000000A508CC78C 7A

实际文件中没有空格,第一部分780010是该行的地址,我希望它是dict的键值,我希望数据部分00802000000010000000000A508CC78C是该键的值.我写了这样的代码:

def __init__(self,filename):
    infile = file(filename,'r')
    self.all_lines = infile.readlines()
    self.dict_by_address = {}

    for i in range(0, self.get_line_number()):
        self.dict_by_address[self.get_address_of_line(i)] = self.get_data_of_line(i)

    infile.close()
Run Code Online (Sandbox Code Playgroud)

get_address_of_line()和get_data_of_line()都是简单的字符串切片函数.get_line_number()遍历self.all_lines并返回一个int

问题是,init进程花了我超过1分钟,是我构造dict错误的方式还是python只需要这么长时间才能做到这一点?

顺便说一句,我是python的新手:)也许代码看起来更像C/C++,任何关于如何编程如python的建议都赞赏:)

Nol*_*lty 9

这样的事怎么样?(我只用了一行就制作了一个测试文件,S21478001000802000000010000000000A508CC78C7A所以你可能需要调整切片.)

>>> with open('test.test') as f:
...     dict_by_address = {line[4:10]:line[10:-3] for line in f}
... 
>>> dict_by_address
{'780010': '00802000000010000000000A508CC78C'}
Run Code Online (Sandbox Code Playgroud)


ste*_*eha 5

这段代码应该比现在的速度快得多.编辑:正如@sth指出的那样,这不起作用,因为实际文件中没有空格.我将在最后添加更正版本.

def __init__(self,filename):
    self.dict_by_address = {}

    with open(filename, 'r') as infile:
        for line in infile:
            _, key, value, _ = line.split()
            self.dict_by_address[key] = value
Run Code Online (Sandbox Code Playgroud)

一些评论:

  • Python中的最佳实践是使用with语句,除非您使用的是没有它的旧Python.

  • 最佳做法是使用open()而不是file(); 我认为Python 3.x甚至没有file().

  • 您可以使用打开的文件对象作为迭代器,当您迭代它时,您将从输入中获得一行.这比调用.readlines()方法更好,方法将所有数据放入列表中; 然后你使用一次数据并删除列表.由于输入文件很大,这意味着您可能会导致交换到虚拟内存,这总是很慢.此版本避免构建和删除巨型列表.

  • 然后,创建了一个巨大的输入行列表,您可以使用range()一个大的整数列表.再次,它浪费时间和内存来构建列表,使用它一次,然后删除列表.您可以通过使用来避免这种开销,xrange()但更好的方法就是随意构建字典,作为从文件中读取行的同一循环的一部分.

  • 使用特殊的切片函数来提取"地址"和"数据"字段可能会更好,但如果输入是常规的(始终遵循示例的模式),您可以执行我在此处显示的操作. line.split()在白色空间上分割线条,给出四个字符串的列表.然后我们使用"解构赋值"将它解压缩为四个变量.由于我们只想保存两个值,因此我使用变量名_(单个下划线)来表示其他两个值.这不是一个真正的语言功能,但它在Python社区中是一个成语:当你有数据时你不关心你可以分配它_.如果有任何数量的值不是4,则该行将引发异常,因此如果可能有空白行或注释行或其他任何值,则应添加检查并处理错误(至少将该行包装在try:/中except).

编辑:更正版本:

def __init__(self,filename):
    self.dict_by_address = {}

    with open(filename, 'r') as infile:
        for line in infile:
            key = extract_address(line) 
            value = extract_data(line)
            self.dict_by_address[key] = value
Run Code Online (Sandbox Code Playgroud)

  • "实际文件中没有空格" (3认同)