【问题标题】:Find differences between two files very slow查找两个文件之间的差异非常慢
【发布时间】:2017-05-23 05:39:22
【问题描述】:

我真的是python的初学者,但试图比较一些从两个数据库中提取的数据到文件中。在脚本中,我为每个数据库内容使用字典,如果发现差异,我将其添加到字典中。它们的键是前两个值(代码和子代码)的组合,值是与该代码/子代码组合关联的 longCodes 列表。总的来说,我的脚本是有效的,但如果它只是结构糟糕且效率低下,我不会感到惊讶。正在处理的样本数据如下:

0,0,83
0,1,157
1,1,158
1,2,159
1,3,210
2,0,211
2,1,212
2,2,213
2,2,214
2,2,215

这个想法是数据应该是同步的,但有时它不是,我试图检测差异。实际上,当我从数据库中提取数据时,每个文件中有超过 100 万行。性能看起来并没有那么好(也许它尽可能好?),大约需要 35 分钟来处理并给我结果。如果有任何提高性能的建议,我很乐意接受!

import difflib, sys, csv, collections

masterDb = collections.OrderedDict()
slaveDb = collections.OrderedDict()
with open('masterDbCodes.lst','r') as f1, open('slaveDbCodes.lst','r') as f2:
    diff = difflib.ndiff(f1.readlines(),f2.readlines())
    for line in diff:
        if line.startswith('-'):
            line = line[2:]
            codeSubCode = ",".join(line.split(",", 2)[:2])
            longCode = ",".join(line.split(",", 2)[2:]).rstrip()
            if not codeSubCode in masterDb:
                masterDb[codeSubCode] = [(longCode)]
            else:
                masterDb[codeSubCode].append(longCode)
        elif line.startswith('+'):
            line = line[2:]
            codeSubCode = ",".join(line.split(",", 2)[:2])
            longCode = ",".join(line.split(",", 2)[2:]).rstrip()
            if not codeSubCode in slaveDb:
                slaveDb[codeSubCode] = [(longCode)]
            else:
                slaveDb[codeSubCode].append(longCode)

f1.close()
f2.close()

【问题讨论】:

  • 我不知道它是否会更快,但是在我的this answer 开头定义的ordereddefaultdict 类可以让您摆脱开头的四行在这两种情况下都使用if not subcode in xxxDb:,并将它们替换为无条件的xxxDb..append(longCode)。另请注意,您不需要关闭这两个文件,with 会自动关闭。

标签: python performance comparison


【解决方案1】:

试试这个:

import difflib, sys, csv, collections

masterDb = collections.OrderedDict()
slaveDb = collections.OrderedDict()
with open('masterDbCodes.lst','r') as f1, open('slaveDbCodes.lst','r') as f2:
    diff = difflib.ndiff(f1.readlines(),f2.readlines())
    for line in diff:
        if line.startswith('-'):
            line = line[2:]
            sp=",".join(line.split(",", 2)[:2])
            codeSubCode = sp
            longCode = sp.rstrip()
            try:
                masterDb[codeSubCode].append(longCode)
            except:
                masterDb[codeSubCode] = [(longCode)]
        elif line.startswith('+'):
            line = line[2:]
            sp=",".join(line.split(",", 2)[:2])
            codeSubCode = sp
            longCode = sp.rstrip()               
            try:
                slaveDb[codeSubCode].append(longCode)
            except:
                slaveDb[codeSubCode] = [(longCode)]

f1.close()
f2.close()

【讨论】:

  • 您可能想查明变化,可能用文字解释您所做的更改以及更改的原因。
  • 我确实尝试了您的代码更改,处理时间为 33 分钟,因此处理时间有所改善。感谢您的意见。
【解决方案2】:

所以我最终使用不同的逻辑来提出一个更有效的脚本。非常感谢https://stackoverflow.com/users/100297/martijn-pieters 的帮助。

#!/usr/bin/python

import csv, sys, collections

masterDb = collections.OrderedDict()
slaveDb = collections.OrderedDict()
outFile = open('results.csv', 'wb')

#First find entries in SLAVE that dont match MASTER
with open('masterDbCodes.lst', 'rb') as master:
    reader1 = csv.reader(master)
    master_rows = {tuple(r) for r in reader1}

with open('slaveDbCodes.lst', 'rb') as slave:
    reader = csv.reader(slave)

    for row in reader:
        if tuple(row) not in master_rows:
            code = row[0]
            subCode = row[1]
            codeSubCode = ",".join([code, subCode])
            longCode = row[2]
            if not codeSubCode in slaveDb:
                slaveDb[codeSubCode] = [(longCode)]
            else:
                slaveDb[codeSubCode].append(longCode)

#Now find entries in MASTER that dont match SLAVE
with open('slaveDbCodes.lst', 'rb') as slave:
    reader1 = csv.reader(slave)
    slave_rows = {tuple(r) for r in reader1}

with open('masterDbCodes.lst', 'rb') as master:
    reader = csv.reader(master)

    for row in reader:
        if tuple(row) not in slave_rows:
            code = row[0]
            subCode = row[1]
            codeSubCode = ",".join([code, subCode])
            longCode = row[2]
            if not codeSubCode in masterDb:
                masterDb[codeSubCode] = [(longCode)]
            else:
                masterDb[codeSubCode].append(longCode)

此解决方案可以在大约 10 秒内处理数据(实际上是两次)。

【讨论】:

    猜你喜欢
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 2011-04-02
    • 2012-02-09
    相关资源
    最近更新 更多