众所周知,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)