首页 > 编程语言 >Python - deepdiff简单使用

Python - deepdiff简单使用

时间:2023-01-11 11:33:22浏览次数:54  
标签:obj Python self 简单 DeepHash 哈希 DeepDiff deepdiff

Python - deepdiff

目录

about#

DeepDiff模块常用来校验两个对象是否一致,并找出其中差异之处,它提供了:

  • DeepDiff:字典,可迭代项,字符串和其他对象的深层差异。它将递归地查找所有更改。
  • DeepSearch:在其他对象中搜索对象。
  • DeepHash:根据对象的内容对其进行哈希处理。

另外,从DeepDiff v3 版本开始,在不同的数据中有两种不同的视图:文本视图(原始)和树视图(新);而DeepHash则是 v4 版本的新功能。

版本情况
DeepDiff适用于Python 3.4、3.5、3.6、3.7,Pypy3

注意:不再支持Python 2。DeepDiff v3.3.0是支持Python 2的最新版本。

下载

pip install deepdiff==4.3.2

DeepDiff#

DeepDiff可以用来校验多种类型的文件内容,如txt、json、图片等......

校验:txt文件

from deepdiff import DeepDiff
"""
a.txt的内容是: abc
b.txt的内容是: abcd
"""
f1, f2 = open('a.txt', 'r', encoding='utf-8').read(), open('b.txt', 'r', encoding='utf-8').read()
print(DeepDiff(f1, f2))  # {'values_changed': {'root': {'new_value': 'abcd', 'old_value': 'abc'}}}

校验:json文件
a.json文件内容:

{
  "title": "V2EX",
  "slogan": "way to explore",
  "description": "创意工作者们的社区",
  "domain": {
    "url": "www.v2ex.com",
    "host": "8080"
  },
  "data": [{"id":"5e4fa8531225c9423dcda9d8","author_id":"51f0f267f4963ade0e08f503","tab":"share"}, {"id":"5e16978581adfe260207a8c1","author_id":"54009f5ccd66f2eb37190485","tab":"share"}]
}

b.json文件内容:

{
  "title": "2VEX",
  "slogan": "way to explore",
  "description": "创意工作者们的社区",
  "domain": {
    "url": "www.v2ex.com",
    "host": "8080"
  },
  "data": [{"id":"5e4fa8531225c9423dcda9d8","tab":"share"}, {"id":"5e16978581adfe260207a8c1","author_id":"54009f5ccd66f2eb37190485","tab":"share_we"}]
}

示例:

import json
from deepdiff import DeepDiff
f1, f2 = json.loads(open('a.json', 'r', encoding='utf-8').read()), json.loads(open('b.json', 'r', encoding='utf-8').read())
print(DeepDiff(f1, f2))  
"""  对比结果
{
    'dictionary_item_removed': [root['data'][0]['author_id']], 
    'values_changed': {
        "root['data'][1]['tab']": {
            'new_value': 'share_we', 
            'old_value': 'share'
        }, 
        "root['title']": {
            'new_value': '2VEX', 
            'old_value': 'V2EX'
        }
    }
}
"""

校验字典

from deepdiff import DeepDiff

t1 = {1:1, 3: 3, 4: 4}
t2 = {1:1, 3: 3, 5: 5, 6: 6}
print(DeepDiff(t1, t2))  # {'dictionary_item_added': [root[5], root[6]], 'dictionary_item_removed': [root[4]]}
print(DeepDiff(t1, t2, view='tree'))  # {'dictionary_item_removed': [<root[4] t1:4, t2:not present>], 'dictionary_item_added': [<root[5] t1:not present, t2:5>, <root[6] t1:not present, t2:6>]}

默认是文本视图;使用树视图请添加view='tree'参数。

DeepSearch#

DeepDiff附带了一个实用程序,可以找到要查找的项目的路径。它被称为Deep Search,它有一个类似于DeepDiff的接口。

如果你有个很深的嵌套结构对象,然后你去查找指定的元素(key和value都行)是否存在,并且返回该元素的路径,Deep Search是个好选择。

来看示例:

from deepdiff import grep

obj = {"long": "somewhere", "string": 2, 0: 0, "somewhere": "around", "a": {"b": {"c": {"d": "somewhere"}}}}
ds1 = obj | grep("somewhere")
print(ds1)  # {'matched_paths': {"root['somewhere']"}, 'matched_values': {"root['long']", "root['a']['b']['c']['d']"}}
ds2 = obj | grep("someone")
print(ds2)  # {}

如上例,指定元素存在则返回它的路径;不存在则返回一个空字典。

DeepHash#

DeepHash以确定的方式根据对象的内容计算对象的哈希。这样,具有相同内容的2个对象应具有相同的哈希值。

DeepHash的主要用途是计算原本无法哈希的对象的哈希。例如,您可以使用DeepHash计算集合或字典的哈希!

DeepHash的核心是将对象确定性序列化为字符串,以便可以将其传递给哈希函数。默认情况下,它使用Murmur 3 128位哈希函数。但是您可以根据需要将另一个哈希函数传递给它。

来看示例:

from deepdiff import DeepHash

obj = {1: 2, 'a': 'b'}
# hash(obj)  # TypeError: unhashable type: 'dict'

我们试图hash上述的字典,但是报错了。
来看使用DeppHash:

from deepdiff import DeepHash

obj = {1: 2, 'a': 'b'}
print(DeepHash(obj))
"""
{
    1: 'c1800a30c736483f13615542e7096f7973631fef8ca935ee1ed9f35fb06fd44e', 
    2: '610e2bb86cee5362640bd1ab01b8a4a4559cced9dd6058376894c041629a7b69', 
    'a': '980410da9522db17c3ab8743541f192a5ab27772a6154dbc7795ee909e653a5c', 
    'b': 'd05faa460a5b4fbbfbd54286ef4e3080f5420c61daf22663163af098cd10182c', 
    '!>*id2118775877424': 'bf5478de322aa033da36bf3bcf9f0599e13a520773f50c6eb9f2487377a7929b'
}
"""

那么在这种情况下obj的哈希到底是什么?DeepHash正在计算obj和obj包含的任何其他对象的哈希。DeepHash的输出是对象ID与其哈希值的字典。为了获取obj本身的哈希,您需要使用对象(或对象的id)来获取其哈希:

from deepdiff import DeepHash

obj = {1: 2, 'a': 'b'}
hashes = DeepHash(obj)
print(DeepHash(obj))
print(hashes[obj])  # bf5478de322aa033da36bf3bcf9f0599e13a520773f50c6eb9f2487377a7929b
# 简写形式
print(DeepHash(obj)[obj])  # bf5478de322aa033da36bf3bcf9f0599e13a520773f50c6eb9f2487377a7929b

另外,DeepDiff倾向于使用Murmur3进行哈希处理。但是,您必须通过运行以下命令手动安装Murmur3:

pip install 'deepdiff[murmur]'

否则,DeepDiff将使用SHA256进行散列,这是加密散列,并且速度相当慢。
deepdiff[murmur]安装遇到问题参考:https://deepdiff.readthedocs.io/en/latest/#troubleshoot

DeepDiff在单元测试中的应用#

先来个unittest框架示例:

import unittest
import requests
from deepdiff import DeepDiff


class MyCase(unittest.TestCase):
    expect = {
        "title": "V2EX",
        "slogan": "way to explore",
        "description": "创意工作者们的社区",
        "domain": "www.v2ex.com"
    }

    @classmethod
    def setUpClass(cls):
        cls.response = requests.get('https://www.v2ex.com/api/site/info.json').json()

    def test_case_01(self):
        self.assertEqual(DeepDiff(self.response, self.expect), {})

    def test_case_02(self):
        self.assertEqual(DeepDiff(self.response['title'], 'v2ex'), {})
        """
        AssertionError: {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} != {}
        """

if __name__ == '__main__':
    unittest.main()

上述的第一个用例,由于实际的请求结果和预期值的json数据都一致,所以DeepDiff返回空字典,然后断言成功;而第二个用例我们修改预期值的title字段值,所以,DeepDiff返回了对比后的结果,与预期值不符,断言失败。
pytest框架中的使用套路是一样的:

import pytest
import requests
from deepdiff import DeepDiff

class TestCase(object):
    expect = {
        "title": "V2EX",
        "slogan": "way to explore",
        "description": "创意工作者们的社区",
        "domain": "www.v2ex.com"
    }

    def setup_class(self):
        self.response = requests.get('https://www.v2ex.com/api/site/info.json').json()

    def test_case_01(self):
        assert not DeepDiff(self.response, self.expect)

    def test_case_02(self):
        assert not DeepDiff(self.response['title'], 'v2ex')
        """
        self = <temp.TestCase object at 0x00000272F7B6FE10>

            def test_case_02(self):
        >       assert not DeepDiff(self.response['title'], 'v2ex')
        
                AssertionError: {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} != {}
        E       AssertionError: assert not {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}}
        E        +  where {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} = DeepDiff('V2EX', 'v2ex')
        
        temp.py:104: AssertionError
        """

if __name__ == '__main__':
    pytest.main(['-v', __file__])

标签:obj,Python,self,简单,DeepHash,哈希,DeepDiff,deepdiff
From: https://www.cnblogs.com/xfbk/p/17043221.html

相关文章

  • typroa和picgo-gitee图床简单配置以及常用快捷键
    目录简介安装for-linux插件picgo-gitee图床1.软件下载安装1.1安装picgo1.2安装nodejs1.3安装picgo-core1.4安装flameshot(截图工具,非必要)1.5安装xclip2.搭建gitee......
  • 浅析 C++ 调用 Python 模块
    作为一种胶水语言,Python 能够很容易地调用 C 、 C++ 等语言,也能够通过其他语言调用 Python 的模块。Python 提供了 C++ 库,使得开发者能很方便地从 C++ 程序中......
  • 极客编程python入门-图形界面
    图形界面Python支持多种图形界面的第三方库,包括:Tk、wxWidgets、Qt、GTK等等。第一步是导入Tkinter包的所有内容:fromtkinterimport*第二步是从​​Frame​​​派生一个​......
  • Python字符串
    1.字符串输出print('数据1','数据2','数据3',sep='',end='\n')数据与数据之间的连接sep=''数据输出之后的换行end='\n'2.字符串转义符转义字符描述......
  • 将Python文件发布成DLL并调用
    如何将Python文件发布成DLL供C/C++调用,试过两种思路:一种是用Cython将Python文件转为.c文件,但是简简单单4行代码,由于调用了NumPy,生成.c文件有5000+行,而且完全找不到原pyt......
  • 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(2)-charles安装激活(Mac)最新简
    1.简介上一篇中宏哥介绍了如何在Windows系统安装激活Charles,那么使用Mac系统的小伙伴或者童鞋们就不高兴了,怎么没有Mac的安装激活教程了。宏哥不能厚此薄彼,今天专门补......
  • go 实现一个简单的web服务
    packagemainimport( "fmt" "log" "net/http" "strings")funcsayhelloName(whttp.ResponseWriter,r*http.Request){ r.ParseForm()//解析参数,默认是不会......
  • python BeautifulReport库 案例失败时报告无法正常换行解决
    python使用BeautifulReport出的测试报告对比其他的一些出报告的工具来说还是挺好看的;BeautifulReport用起来也很方便;但是git上下载的BeautifulReport,当测试案例失败时,案例......
  • Django序列化器的简单使用
    [Django序列化器的简单使用-SSgeek-博客园](https://www.cnblogs.com/ssgeek/p/13263810.html)注意:serializer 不是只能为数据库模型类定义,也可以为非数据库模型类的......
  • Python变量
    1.变量介绍变量分为变量名、变量值、内存地址id()获取变量的内存地址作用:判断两个数据是否是同一个数据变量的作用:存储数据更方便的管理和使用例:print(id(name))#......