如何在python

时间:2018-01-20 13:16:56

标签: python

我有一个超过400万行的文件,我想逐行阅读,并在第一个"列上执行操作"数据的。可能存在重复数据,我想确保我只执行一次这些操作,并且能够重新启动程序并从中断处开始。

我的解决方案是解析该行,将值存储到列表中,然后"如果x不在列表中,则#34;执行操作,然后在程序死亡/停止/被杀死时将该列表存储为pickle。

然而,脚本在运行几个小时之后会出现段错误,我认为这是因为我已经烧掉了我所有的ram,因为在checkedFile列表中存储了很多MD5总和。

因为文件太大(400万条+条目),我需要一些快速查找的东西,希望有一个简单的解决方案。谢谢!

数据如下所示:6e5f6c90e6bf31c31283afb8dca93da8 | mouse.gif | 10102017

我目前的代码如下:

checkedFile = []

def readline(inFile):
print("Opening file: %s\n" % inFile)
try:
    with open(inFile, "r") as inputFile:
        for line in inputFile: # read in file line by line
            fileHash, garbage = line.split("|",1) 
            if fileHash not in checkedFile:
                checkedFile.append(fileHash)
                checkit(fileHash) # 

1 个答案:

答案 0 :(得分:2)

我想你会遇到的一个问题是你选择的数据结构。由于checkedFile是一个列表,因此检查列表中的哈希值是否为O(N) time complexity。我的第一个建议是使用python set。这使用的哈希映射的性能为O(1)

checkedFile = set()

def readline(inFile):
    print("Opening file: %s\n" % inFile)
    with open(inFile, "r") as inputFile:
        for line in inputFile: # read in file line by line
            fileHash, garbage = line.split("|",1) 
            if fileHash not in checkedFile:
                checkedFile.add(fileHash)
                checkit(fileHash)

Python只为2 reasons提供了真正的段错误,所以你肯定会耗尽内存。我发现你对列表存储进行了分类是很奇怪的,因为每个哈希都是16字节* 4百万= 64Mb,我想在你的典型计算机中没有接近ram的数量。

走稳定存储路径我建议使用sqlite。这种方法不会耗尽内存,因为它将存储在您的硬盘上。

 import sqlite3
 connection = sqlite3.connect('cache.db')
 CREATE_CACHE_TABLE = '''CREATE TABLE IF NOT EXISTS cache ( 
                         hash TEXT PRIMARY KEY
               )'''
 SELECT_STATEMENT = 'SELECT hash FROM cache WHERE hash = ?'
 INSERT_STATEMENT = 'INSERT INTO cache VALUES ?'

 with connection:
     connection.execute(CREATE_CACHE_TABLE)
 with open(inFile, "r") as inputFile:
      for line in inputFile:
          fileHash, garbage = line.split("|", 1)
          with connection:
               if not connection.execute(SELECT_STATMENT, (fileHash,)).fetchone():
                    connection.execute(INSERT_STATEMENT, (fileHash,))
                    checkit(fileHash)

作为额外奖励,您还可以缓存checkit的结果,以便在出于某种原因停止时可以恢复计算。这也有利于您,因为Web请求的最短响应时间为10ms。您提到Web请求返回json响应。我在sqlite with python之前写过如何在sqlite中存储json的文章。您需要修改函数checkit以返回json数据。

import sqlite3
import json

def adapt_json(data):
    return (json.dumps(data, sort_keys=True)).encode()

def convert_json(blob):
    return json.loads(blob.decode())

sqlite3.register_adapter(dict, adapt_json)
sqlite3.register_converter('JSON', convert_json)

connection = sqlite3.connect('cache.db', detect_types=sqlite3.PARSE_DECLTYPES)
CREATE_CACHE_TABLE = '''CREATE TABLE IF NOT EXISTS cache (
                         hash TEXT PRIMARY KEY,
                         check_results JSON
               )'''
SELECT_STATEMENT = 'SELECT hash FROM cache WHERE hash = ?'
INSERT_STATEMENT = 'INSERT INTO cache VALUES ?, ?'

with connection:
    connection.execute(CREATE_CACHE_TABLE)
with open(inFile, "r") as inputFile:
    for line in inputFile:
        fileHash, garbage = line.split("|", 1)
        with connection:
            if not connection.execute(SELECT_STATMENT, (fileHash,)).fetchone():
                json_data = checkit(fileHash)
                connection.execute(INSERT_STATEMENT, (fileHash, json_data))

如果你使用这种最终方法。您可以与文件的不同块并行运行此程序,它仍然可以工作。如果你最终得到一个更大的文件,这种方法也应该很好地扩展。