Python-glom的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/y472360651/article/details/82768860

glom是一种用Python处理数据的新方法,具有以下特点:

  • 嵌套结构并基于路径访问
  • 使用轻量级的Pythonic规范进行声明性数据转换
  • 可读、有意义的错误信息
  • 内置数据探测和调试功能

接下来,将记录一下glom的使用:

安装

pip3 install glom

举个栗子

假设有这样一个数据,结构如下:

d = {"a": {"b": {"c": 1}}}

此时,我们可以使用glom来获取到最里面c所对应的值,用法如下:

from glom import glom

d = {"a": {"b": {"c": 1}}}
print(glom(d, "a.b.c"))     # 1

通常来说,我们获取这种结构的数据,都是采用如下方式:

print(d["a"]["b"]["c"])     # 1

从而获取到数据。这看起来也是非常简单的对吧,但是通常情况下,不会这么顺利,也有可能会遇到空值得情况,如下:

d = {"a": {"b": None}}
print(d["a"]["b"]["c"])

Traceback (most recent call last):
  ...
    print(d["a"]["b"]["c"])
TypeError: 'NoneType' object is not subscriptable

我们得到了一个错误提示,但是这对我们而言没有任何作用,错误消息甚至没有告诉我们哪个访问失败。对于这种情况,我们再来看一下glom的处理方式,如下:

from glom import glom

d = {"a": {"b": None}}
print(glom(d, "a.b.c"))

Traceback (most recent call last):
  ...
glom.core.PathAccessError: could not access 'c', part 2 of Path('a', 'b', 'c'), got error: AttributeError("'NoneType' object has no attribute 'c'",)

如此错误提示还算差不多,我们可以阅读,理解,并采取行动!

超越访问

首先,我们来看一下glom方法:

glom(target, spec, **kwargs)

首先,我们来介绍一下这几个参数:

  • target:我们的数据,可以是dict、list或者其他任何对象
  • spec:是我们希望输出的内容

现在我们一组特殊的数据,我们希望通过glom来将它们获取出来,数据如下:

data = {"student": {"info": [{"name": "laozhang"}, {"name": "laowang"}]}}

现在我们希望能搞列出所有name的数据,我们可以通过glom来实现,代码如下:

from glom import glom

info = glom(data, ("student.info", ["name"]))
print(info)     # ['laozhang', 'laowang'], 为一个list

此时,我们不想用一个列表来接收他们,我希望通过一个字典,并赋予一个键来接收,如下:

from glom import glom

info = glom(data, {"info": ("student.info", ["name"])})
print(info)     # {'info': ['laozhang', 'laowang']}, 为一个dict

改变要求

不幸的是,现实中的数据很混乱,你可能期待某种格式,结果却得到了完全不同的结果。例如有这样两组数据:

from glom import glom, Coalesce

data_1 = {"school": {"student": [{"name": "laozhang"}, {"name": "laowang"}]}}
data_2 = {"school": {"teacher": [{"name": "张老师"}, {"name": "王老师"}]}}

spec = {"name": (Coalesce("school.student", "school.teacher"), ["name"])}
 
print(glom(data_1, spec))       # {'name': ['laozhang', 'laowang']}
print(glom(data_2, spec))       # {'name': ['张老师', '王老师']}

Coalesce是一个glom结构,允许你为你的子目录指定回退行为。但是,如果有一组数据,同时满足Coalesce中的所有匹配,那么它将会依次匹配,直到满足匹配为止。即在上面的栗子中,如果数据同事匹配school.studentschool.teacher,会取出匹配的school.student的数据,而不会往下匹配了!!!

Python工具

大多数其他实现都局限于特定的数据格式或纯模型,无论是jmespath还是Xpath/XSLTglom没有牺牲其实用性,而是充分利用Python本身的强大功能。假设有这样的数据:

data = {"school": {"student": [{"name": "laozhang", "age": 18}, {"name": "laowang", "age": 20}]}}

然后,我们需要统计所有age的和,此时,我们可以使用glom这样操作:

from glom import glom

spec = {"sum_age": ("school.student", ["age"], sum)}
print(glom(data, spec))         # {"sum_age": 38}

联系点

glom是一种实用的生产工具,为了更好的演示如何使用它,我们将构建一个API响应。我们正在实现一个联系人Web页面,如地址簿,但是需要一个ORM/数据库,并且兼容Web和移动前端。下面,我们创建一个联系人模型:

from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("mysql+pymysql://root:[email protected]/test?charset=utf8")
Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(20))
    age = Column(Integer)
    create_time = Column(DateTime)
    
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

u1 = User(name="laowang", age=20, create_time=datetime.now())
u2 = User(name="laozhang", age=18, create_time=datetime.now())
session.add_all([u1, u2])
session.commit()

然后,我们可以使用ORM来获取数据:

data = session.query(User).all()

接下来我们设置指定结果的格式,而后使用glom进行处理,代码如下:

spec = {
    "result": [{
        "user_id": "id",
        "user_name": "name",
        "user_age": "age",
        "create_time": "create_time"
    }]
}
print(glom(data, spec))

############## 结果如下 ##############
{
	'result': [{
		'id': 1,
		'name': 'laozhang',
		'age': 18,
		'create_time': datetime.datetime(2018, 9, 19, 10, 8, 19)
	}, {
		'id': 2,
		'name': 'laowang',
		'age': 20,
		'create_time': datetime.datetime(2018, 9, 19, 10, 8, 28)
	}]
}

spec的格式可以看出,键可以任何有意义的名称,而值只可以为ORM中对应的类属性名称!!至此,Over~~~

猜你喜欢

转载自blog.csdn.net/y472360651/article/details/82768860
今日推荐