我有一个超过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) #
答案 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))
如果你使用这种最终方法。您可以与文件的不同块并行运行此程序,它仍然可以工作。如果你最终得到一个更大的文件,这种方法也应该很好地扩展。