前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >records包源码解析

records包源码解析

作者头像
哒呵呵
发布2018-12-19 11:10:27
7130
发布2018-12-19 11:10:27
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

records包是为了让人们更加方便的使用数据库的中的数据,简洁但强大。

使用

  • 连接数据库
代码语言:javascript
复制
import records

db = records.Database('postgres://...')
rows = db.query('select * from active_users') 

rows返回的是一个迭代器

代码语言:javascript
复制
>>> rows[0]
<Record {"username": "model-t", "active": true, "name": "Henry Ford", "user_email": "model-t@gmail.com", "timezone": "2016-02-06 22:28:23.894202"}>

也可以使用更加优雅的方式读取数据

代码语言:javascript
复制
row.user_email, row['user_email'] 或者是 row[3]

或者是将数据全部取出来

代码语言:javascript
复制
>>> rows.all()
[<Record {"username": ...}>, <Record {"username": ...}>, <Record {"username": ...}>, ...]

rows还贴心的把数据变成字典

代码语言:javascript
复制
rows.as_dict() 或 rows.as_dict(ordered=True)

records包支持将数据导出成各种格式

代码语言:javascript
复制
csv tsv json yaml html xls xlsx dbf latex ods

>>> print(rows.export('csv'))
username,active,name,user_email,timezone
model-t,True,Henry Ford,model-t@gmail.com,2016-02-06 22:28:23.894202
...

源码解析

核心类有三个 Record, RecordCollection, Database。在做源码分析时,先从入口类Database开始:

Database类

Database类的核心是sqlalchemy框架,初始化时会根据给定的数据库url,调用create_engine方法,连接数据库。在Database还实现了__enter__和__exit__方法,以方便使用上下文管理器语法。Database类的核心方法是query,其他的query_file, bulk_query_file都是基于它做的。bulk_query 和 transaction 直接调用了sqlalchemy的excute和begin方法。

query方法中首先调用了execute返回一个游标cursor,再继而使用了Record和RecordCollection,构成了类似于迭代器的chain。

代码语言:javascript
复制
def query(self, query, fetchall=False, **params):
        """Executes the given SQL query against the Database. Parameters
        can, optionally, be provided. Returns a RecordCollection, which can be
        iterated over to get result rows as dictionaries.
        """

        # Execute the given query.
        cursor = self.db.execute(text(query), **params) # TODO: PARAMS GO HERE

        # Row-by-row Record generator.
        row_gen = (Record(cursor.keys(), row) for row in cursor)

        # Convert psycopg2 results to RecordCollection.
        results = RecordCollection(row_gen)

        # Fetch all results if desired.
        if fetchall:
            results.all()

        return results
Record类

Record类使用cursor方法返回的key和value,也就是列名和相应的数据做进一步的处理。为了更方便的使用,Record类的__getitem__实现了序列协议,__getattr__实现了基于__getitem__实现了动态属性。 as_dict方法实现了元组到字典的转换,实现思路值得参考:

代码语言:javascript
复制
def as_dict(self, ordered=False):
    """Returns the row as a dictionary, as ordered."""
    items = zip(self.keys(), self.values())

    return OrderedDict(items) if ordered else dict(items)
代码语言:javascript
复制

dataset使用了property装饰器将方法变成了属性,其中使用records包作者开发的tablib包,并且使用方法_reduce_datetimes将datetime类型转换成iso的字符串格式。同理将数据导出成json,csv等格式也是复用了tablib的代码。

代码语言:javascript
复制
def _reduce_datetimes(row):
    """Receives a row, converts datetimes to strings."""

    row = list(row)

    for i in range(len(row)):
        if hasattr(row[i], 'isoformat'):
            row[i] = row[i].isoformat()
    return tuple(row)
RecordCollection类

RecordCollection类和Record类大部分方法相似,但是实现了__iter__和__next__的迭代器协议。这是为了尽量不一次性将数据读入内存,在需要的时候才进行计算。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用
  • 源码解析
    • Database类
      • Record类
        • RecordCollection类
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档