比较字典列表

时间:2015-05-05 15:18:19

标签: python list dictionary iterator

我正在开发一个处理解析电子邮件并将其保存到数据库的项目。解析电子邮件并将解析后的电子邮件保存到日志文件可以正常工作,但是当我尝试从日志文件中读取时,我遇到了一个奇怪的问题。这是代码:

def main():
global email_batch, temp_email_batch

read_logfile = True
while read_logfile:
    try:
        with open('a-1-test.json', 'r') as outfile:
            temp_email_batch = json.load(outfile)
            outfile.close()
    except IOError as err:
        print "I/O error({0}): {1}".format(err.errno, err.strerror)
    except:
        print "Unexpected error:", sys.exc_info()[0]

    if temp_email_batch != email_batch:
        email_batch = temp_email_batch
        print "not equal log files"
        # saveData()
        for parsedMail in email_batch:
            collection.insert(parsedMail)
    else:
        print "equal log files"
        time.sleep(10)

我可以读取日志文件(这里只是一个json格式的测试文件)并保存数据。检查:

if temp_email_batch != email_batch:

当我尝试比较两批时,有一种奇怪的行为。我的想法是检查我是否已从日志文件中获取数据,或者是否已将新数据写入日志文件。如果我注释掉迭代:

for parsedMail in email_batch:
            # http_client.addRawData(sourceName, parsedMail)
            collection.insert(parsedMail)

检查工作正常,并且看到没有新数据添加到日志文件中,但是如果我取消注释它,即使temp_email_batch与电子邮件地址相同,检查也始终为真,因此它会一直保存相同的电子邮件集合。

我非常惊讶。迭代器是否以某种方式改变了列表?我所有的编程直觉都说它没有,但是如果只是通过评论代码可以毫无问题地运行,并且如果temp等于前一个批次就跳转到else子句,那肯定存在问题。

提前谢谢你, 的Georgi

编辑:

所以我找到了一个解决方法,不直接通过pymongo库将我的数据保存到数据库,而是使用json远程进程调用并设置一个脚本来定义数据库操作的几种方法。通过使用RPC我没有问题,代码工作正常。

1 个答案:

答案 0 :(得分:0)

这不是在Python中如何实现dict或list相等的问题。

Python中的列表相等性取决于大小,顺序和包含值的相等性。这意味着,在建立两个相同大小的列表之后,解释器将基本上压缩两个列表并依次对每个列表调用==。

Dict平等是相似的,只是它们无序,所以顺序没有因素。它可以在概念上被认为是从每个字典创建一组键值对并询问它们是否是不等。

我要到这里来的是,这两个词组必须真的是不平等的,而我95%肯定这是因为你忘了那些词汇是可变的而且PyMongo,当您将dict插入或保存到集合时,会将一个_id字段添加到dict中。请记住,dict是可变的 - 在运行时对dict的所有引用现在也都有_id字段。

但是,JSON文件当然在运行时之外。当您再次加载dicts时,他们没有该字段。对于你,并且对于大多数意图和目的,两个dicts列表可能看起来是相同的,但由于旧列表的每个dicts中的_id字段,它们现在是不相等的。

如果你想保持这条路线,你将需要避免比较中的_id字段(hacky)。或者,您可以为集合设置唯一键并处理将引发的重复键错误(最好的选择,可能是,如果您真的关心重复项)。或者,您可以在将每个字典写入数据库之前复制每个字典,然后编写副本而不是原始字典,以便旧的引用不会获得新字段(也是hacky)。实际上,这需要您更仔细地考虑如何定义数据结构的相等性。

欢迎来到可变状态。太糟糕了。