peewee-async支持sqlite异步

众所周知,peewee-async 官方不支持sqlit。可以使用以下代码代替。

async_sqlite.py

"""
peewee-async  非官方支持sqlite异步代码, 可能因为aiosqlite不支持连接池,所有官方异步不支持sqlite异步。 代码时候list存储多个数据库连接句柄代替连接池使用,实现了peewee异步使用sqlite,性能上可能比不上使用真正的连接池,但是都用sqlite了就不考虑性能方面的问题了

@Version:   0.1 (peewee==3.17.5,peewee-async==0.10.0)
@Auth:      John(zy1234500@outlook.com)
@Date:      2024-06-11
@Reference: https://gist.github.com/xsduan/09fb145da3da3a78f5ca844b155f27aa (The source supports only the lower version of peewee)
"""

import functools
import peewee
from peewee_async import AsyncDatabase, register_database
import playhouse.sqlite_ext as sqlite_ext


try:
    import aiosqlite
except ImportError:
    aiosqlite = None


class AsyncSqliteConnection:
    def __init__(self, *, database=None, loop=None, timeout=None, **kwargs):
        self._created_connections = []
        self.loop = loop
        self.database = database
        self.timeout = timeout
        self.connect_kwargs = kwargs

    async def acquire(self):
        conn = self.conn
        try:
            res = await conn.__aenter__()
        except RuntimeError:
            conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)
            res = await conn.__aenter__()
        self._created_connections.append(conn)
        return res

    async def release(self, conn):
        if conn in self._created_connections:
            self._created_connections.remove(conn)
        await conn.commit()
        await conn.__aexit__(None, None, None)

    async def connect(self):
        self.conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)

    async def close(self):
        for conn in self._created_connections:
            await conn.__aexit__(None, None, None)
        self._created_connections = []

    async def cursor(self, conn=None, *args, **kwargs):
        in_transaction = conn is not None
        if not conn:
            conn = await self.acquire()
        cursor = await conn.cursor()
        cursor.release = functools.partial(
            self.release_cursor, cursor,
            in_transaction=in_transaction)
        return cursor

    async def release_cursor(self, cursor, in_transaction=False):
        conn = cursor._conn
        await cursor.__aexit__(None, None, None)
        if not in_transaction:
            await self.release(conn)


class AsyncSqliteMixin(AsyncDatabase):
    if aiosqlite:
        import sqlite3

        Error = sqlite3.Error
        
    def init(self, database, **kwargs):
        if not aiosqlite:
            raise Exception("Error, aiosqlite is not installed!")
        self._async_conn_cls = kwargs.pop('async_conn', AsyncSqliteConnection)
        super().init(database, **kwargs)

    def init_async(self, conn_class=AsyncSqliteConnection):
        if not aiosqlite:
            raise Exception("Error, aiosqlite is not installed!")
        self._async_conn_cls = conn_class

    @property
    def connect_kwargs_async(self):
        return {**self.connect_kwargs}

    async def last_insert_id_async(self, cursor, *args, **kwargs):
        """Get ID of last inserted row.
        """
        model = None
        if model_ := kwargs.get('model'):
            model = model_
        elif args:
            model = args[0]
        if not model:
            return cursor.lastrowid
        elif model._meta.auto_increment:
            return cursor.lastrowid

    @property
    def connect_params_async(self):
        """Connection parameters for `aiomysql.Connection`
        """
        kwargs = self.connect_params.copy()
        return kwargs
    
    @property
    def use_speedups(self):
        return False

    @use_speedups.setter
    def use_speedups(self, value):
        pass

class SqliteDatabase(AsyncSqliteMixin, peewee.SqliteDatabase):
    def init(self, database, **kwargs):
        super().init(database, **kwargs)
        self.init_async()


class SqliteExtDatabase(SqliteDatabase, sqlite_ext.SqliteExtDatabase):
    pass


register_database(
    SqliteDatabase, 
    'sqlite',
    'sqliteext',
    'sqlite+pool',
    'sqliteext+pool',
)

使用例子:

使用方法和peewee-async的例子基本一致,可以参考peewee-async的官方文档 https://peewee-async.readthedocs.io/en/latest/

main.py

import asyncio
import peewee
import peewee_async

from async_sqlite import SqliteDatabase

database = SqliteDatabase('sqlite.db')  # 只有这里不一样
objects = peewee_async.Manager(database)


class TestModel(peewee.Model):
    text = peewee.CharField()

    class Meta:
        database = database

async def handler():
    await objects.create(TestModel, text="Not bad. Watch this, I'm async!")
    all_objects = await objects.execute(TestModel.select())
    for obj in all_objects:
        print(obj.text)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值