文章目录

十三 Playhouse,Peewee 的扩展13.1 Sqlite 扩展13.2 SqliteQ13.2.1 事务 Transactions13.2.2 代码示例

13.3 Sqlite 用户定义函数13.3.1 函数,按集合名称列出13.3.1.1 控制流 CONTROL_FLOW13.3.1.2 日期 DATE13.3.1.3 文件 FILE13.3.1.4 数学 MATH13.3.1.5 STRING

十三 Playhouse,Peewee 的扩展

http://docs.peewee-orm.com/en/latest/peewee/playhouse.html Peewee 带有许多扩展模块,这些扩展模块收集在 playhouse命名空间下。尽管名字很傻,但还是有一些非常有用的扩展,尤其是那些公开了特定于供应商的数据库功能的扩展,例如SQLite Extensions和Postgresql Extensions扩展。

您将在下面找到构成playhouse.

数据库驱动程序/供应商特定的数据库功能

SQLite 扩展(在它自己的页面上) SqliteQ Sqlite 用户定义函数 apsw,一个高级的 sqlite 驱动程序 Sqlcipher 后端 Postgresql 扩展 Cockroach数据库 MySQL 扩展 高级功能 字段 Fields 捷径 Shortcuts 混合属性 Hybrid Attributes 键/值存储 Key/Value Store 信号支持 Signal support 数据集 DataSet 数据库管理和框架集成 pwiz,模型生成器 pwiz, a model generator 架构迁移 Schema Migrations 连接池 Connection pool 映射 Reflection 数据库网址 Database URL 测试工具 Test Utils Flask实用程序 Flask Utils

13.1 Sqlite 扩展

Sqlite 扩展已移至它们自己的页面。

13.2 SqliteQ

该playhouse.sqliteq模块提供了 的子类 SqliteExtDatabase,它将序列化并发写入 SQLite 数据库。如果您想 从多个线程对 SQLite 数据库进行简单的读写访问,SqliteQueueDatabase可以将其用作常规的替代品。SqliteDatabase

SQLite 只允许一个连接在任何给定时间写入数据库。因此,如果您有一个需要写入数据库的多线程应用程序(例如 Web 服务器),当一个或多个尝试写入的线程无法获取锁时,您可能会偶尔看到错误。

SqliteQueueDatabase旨在通过单个长期连接发送所有写入查询来简化事情。好处是您可以看到多个线程写入数据库而不会发生冲突或超时。然而,缺点是您不能发出包含多个查询的写入事务——本质上,所有写入都在自动提交模式下运行。

笔记 该模块得名于所有写查询都被放入线程安全队列的事实。单个工作线程侦听队列并执行发送给它的所有查询。

13.2.1 事务 Transactions

由于所有查询都由单个工作线程序列化和执行,因此来自不同线程的事务性 SQL 可能会乱序执行。在下面的示例中,线程“B”启动的事务被线程“A”回滚(后果很糟糕!):

线程 A:UPDATE 移植 SET organ=‘liver’, …;线程 B:开始事务;线程 B: UPDATE life_support_system SET timer += 60 …;线程 A:回滚;- 不好了…。 由于来自不同事务的查询可能会被交错,因此transaction()和 atomic()方法在SqliteQueueDatabase.

对于希望从不同线程临时写入数据库的情况,可以使用pause()和 unpause()方法。这些方法会阻塞调用者,直到编写者线程完成其当前工作负载。然后编写器断开连接,调用者接管,直到unpause被调用。

start()、stop()和is_stopped()方法也可用于控制编写器线程。

笔记 查看 SQLite 的隔离 文档,了解有关 SQLite 如何处理并发连接的更多信息。

13.2.2 代码示例

创建数据库实例不需要任何特殊处理。不过, SqliteQueueDatabase接受一些您应该注意的特殊参数。如果您使用gevent,则必须use_gevent=True在实例化数据库时指定 - 这样 Peewee 将知道使用适当的对象来处理队列、线程创建和锁定。

from playhouse.sqliteq import SqliteQueueDatabase

db = SqliteQueueDatabase(

'my_app.db',

use_gevent=False, # Use the standard library "threading" module.

autostart=False, # The worker thread now must be started manually.

queue_max_size=64, # Max. # of pending writes that can accumulate.

results_timeout=5.0) # Max. time to wait for query to be executed.

如果autostart=False,如上例所示,您将需要调用 start()以启动将执行实际写入查询执行的工作线程。

@app.before_first_request

def _start_worker_threads():

db.start()

如果您计划执行 SELECT 查询或通常想要访问数据库,您将需要调用connect()和 调用close()任何其他数据库实例一样。

当您的应用程序准备好终止时,使用该stop() 方法关闭工作线程。如果有工作积压,则此方法将阻塞,直到所有待处理的工作完成(尽管不允许新工作)。

import atexit

@atexit.register

def _stop_worker_threads():

db.stop()

最后,该is_stopped()方法可用于确定数据库编写器是否已启动并正在运行。

13.3 Sqlite 用户定义函数

playhouse 模块包含许多用户定义的sqlite_udf函数、聚合和表值函数,您可能会发现它们很有用。这些功能被分组在集合中,您可以按集合单独注册这些用户定义的扩展,或注册所有内容。

标量函数是接受多个参数并返回单个值的函数。例如,将字符串转换为大写,或计算 MD5 十六进制摘要。

聚合函数类似于对多行数据进行操作并产生单个结果的标量函数。例如,计算整数列表的总和,或查找特定列中的最小值。

表值函数只是可以返回多行数据的函数。例如,返回给定字符串中所有匹配项的正则表达式搜索函数,或接受两个日期并生成所有中间日期的函数。

笔记 要使用表值函数,您需要构建 playhouse._sqlite_extC 扩展。

注册用户自定义函数:

db = SqliteDatabase('my_app.db')

# Register *all* functions.

register_all(db)

# Alternatively, you can register individual groups. This will just

# register the DATE and MATH groups of functions.

register_groups(db, 'DATE', 'MATH')

# If you only wish to register, say, the aggregate functions for a

# particular group or groups, you can:

register_aggregate_groups(db, 'DATE')

# If you only wish to register a single function, then you can:

from playhouse.sqlite_udf import gzip, gunzip

db.register_function(gzip, 'gzip')

db.register_function(gunzip, 'gunzip')

使用库函数(“hostname”):

# Assume we have a model, Link, that contains lots of arbitrary URLs.

# We want to discover the most common hosts that have been linked.

query = (Link

.select(fn.hostname(Link.url).alias('host'), fn.COUNT(Link.id))

.group_by(fn.hostname(Link.url))

.order_by(fn.COUNT(Link.id).desc())

.tuples())

# Print the hostname along with number of links associated with it.

for host, count in query:

print('%s: %s' % (host, count))

13.3.1 函数,按集合名称列出

标量函数用 表示(f),聚合函数用表示(a),表值函数用表示(t)。

13.3.1.1 控制流 CONTROL_FLOW

if_then_else(cond,truthy[,falsey=None])

简单的三元类型运算符,其中,根据 cond参数的真实性,将返回truthyor值。falsey

13.3.1.2 日期 DATE

strip_tz(date_str)

参数: date_str– 日期时间,编码为字符串。 返回: 删除任何时区信息的日期时间。 时间没有以任何方式调整,时区被简单地删除。

humandelta(nseconds[,glue=' , '])

参数:

nseconds ( int ) – timedelta 中的总秒数。glue( str ) – 连接值的片段。 返回: 易于阅读的 timedelta 描述。

例如,86471 -> “1 天 1 分钟 11 秒”

mintdiff(datetime_value)

参数: datetime_value– 日期时间。 返回: 列表中任意两个值之间的最小差异。 计算任何两个日期时间之间的最小差异的聚合函数。

avgtdiff(datetime_value)

参数: datetime_value– 日期时间。 返回: 列表中值之间的平均差异。 计算列表中连续值之间的平均差异的聚合函数。

duration(datetime_value)

参数: datetime_value– 日期时间。 返回: 列表中从最小值到最大值的持续时间,以秒为单位。 计算列表中从最小值到最大值的持续时间的聚合函数,以秒为单位返回。

date_series(start, stop[, step_seconds=86400])

参数: start ( datetime ) – 开始日期时间 stop ( datetime ) – 停止日期时间 step_seconds ( int ) – 组成步骤的秒数。 表值函数,它返回包含从开始到停止一次迭代遇到的日期/时间值的行step_seconds。

此外,如果 start 没有时间组件并且 step_seconds 大于或等于一天(86400 秒),则返回的值将是日期。相反,如果 start 没有日期组件,则值将作为时间返回。否则,值将作为日期时间返回。

例子:

SELECT * FROM date_series('2017-01-28', '2017-02-02');

value

-----

2017-01-28

2017-01-29

2017-01-30

2017-01-31

2017-02-01

2017-02-02

13.3.1.3 文件 FILE

file_ext(filename)

参数: 文件名( str ) – 要从中提取扩展名的文件名。 返回: 返回文件扩展名,包括前导“.”。

file_read(filename)

参数: 文件名( str ) – 要读取的文件名。 返回: 文件的内容。 帮手

gzip(data[,compression=9])

参数:

data ( bytes ) – 要压缩的数据。compression ( int ) – 压缩级别(最大为 9)。 返回: 压缩的二进制数据。

gunzip(data)

参数: 数据( bytes ) – 压缩数据。 返回: 未压缩的二进制数据。

hostname(url)

参数: url( str ) – 从中提取host的 URL。 返回: URL 的host部分

toggle(key)

参数: 钥匙– 切换键。 在真/假状态之间切换键。例子:

>>> toggle('my-key')

True

>>> toggle('my-key')

False

>>> toggle('my-key')

True

setting(key[, value=None])

参数:

key - 设置/检索的密钥。value – 要设置的值。 返回: 与键关联的值。

在内存中存储/检索设置并在应用程序的生命周期内持续存在。要获取当前值,只需指定键。要设置新值,请使用键和新值调用。

clear_toggles()

清除与函数关联的所有状态toggle()。

clear_settings()

清除与函数关联的所有状态setting()。

13.3.1.4 数学 MATH

randomrange(start[, stop=None[, step=None]])

参数:

start ( int ) – 范围的开始(包括)end ( int ) – 范围结束(不包括)step ( int ) – 返回值的时间间隔。 返回 之间的随机整数。[start, end)

gauss_distribution(mean,sigma)

参数:

mean ( float ) – 平均值sigma ( float ) – 标准差

sqrt( n )

计算 的平方根n。

tonumber(s)

参数: s( str ) – 要转换为数字的字符串。 返回: 整数、浮点数或失败时为 NULL。

mode(val)

参数: 值– 列表中的数字。 返回: 观察到的众数或最常见的数字。 计算值模式的聚合函数。

minrange(val)

参数: 值- 价值 返回: 两个值之间的最小差异。 聚合函数,计算序列中两个数字之间的最小距离。

avgrange(val)

参数: 值- 价值 返回: 值之间的平均差异。 聚合函数,计算序列中两个连续数字之间的平均距离。

range(val)

参数: 值- 价值 返回: 按顺序从最小值到最大值的范围。 返回观察值范围的聚合函数。

median(val)

参数: val- 价值 返回: 序列中的中值或中间值。 聚合函数,计算序列中的中间值。

笔记 仅当您编译了_sqlite_udf扩展时才可用。

13.3.1.5 STRING

substr_count(haystack,needle)

needle返回出现的次数haystack。

strip_chars(haystack,chars)

chars从 . 的开头和结尾删除任何字符haystack。

damerau_levenshtein_dist( s1 , s2 )

使用 levenshtein 算法的 damerau 变体计算从 s1 到 s2 的编辑距离。

笔记 仅当您编译了_sqlite_udf扩展时才可用。

levenshtein_dist( s1 , s2 )

使用 levenshtein 算法计算从 s1 到 s2 的编辑距离。

笔记 仅当您编译了_sqlite_udf扩展时才可用。

str_dist( s1 , s2 )

使用标准库 SequenceMatcher 的算法计算从 s1 到 s2 的编辑距离。

笔记 仅当您编译了_sqlite_udf扩展时才可用。

regex_search(regex,search_string)

参数: regex ( str ) – 正则表达式 search_string ( str ) – 用于搜索正则表达式实例的字符串。 表值函数,用于在字符串中搜索与提供的regex. 返回找到的每个匹配项的行。

例子:

SELECT * FROM regex_search('\w+', 'extract words, ignore! symbols');

value

-----

extract

words

ignore

symbols

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: