被阻止的Python异步函数调用也会阻止另一个异步函数
我使用FastAPI开发访问SQL Server的数据层API。 无论是使用pytds还是pyodbc, 如果有数据库事务导致任何请求挂起, 所有其他请求都将被阻止。(即使没有数据库操作) 复制:被阻止的Python异步函数调用也会阻止另一个异步函数,python,python-3.x,python-asyncio,fastapi,Python,Python 3.x,Python Asyncio,Fastapi,我使用FastAPI开发访问SQL Server的数据层API。 无论是使用pytds还是pyodbc, 如果有数据库事务导致任何请求挂起, 所有其他请求都将被阻止。(即使没有数据库操作) 复制: 有意执行可序列化的SQL Server会话,开始事务,不回滚或提交 使用异步处理程序函数向API发送请求,如下所示: 并使用异步处理程序函数向同一应用程序的API发送请求,如下所示: 我预计步骤2会挂起,步骤3会在2秒后直接返回。 但是,如果事务没有提交或回滚,则步骤3永远不会返回 如何使这些处理程序
如何使这些处理程序函数同时工作?原因是
rs=future.result()
实际上是一个阻塞调用-请参阅。不幸的是,executor.submit()
没有返回可等待的对象(concurrent.futures.Future
不同于asyncio.Future
)
您可以使用asyncio.wrap_future
,它接受concurrent.future
并返回asyncio.future
(请参阅)。新的future
对象是可等待的,因此您可以将阻塞函数转换为异步函数
一个例子:
导入异步IO
进口期货
async def my_async():
以concurrent.futures.ThreadPoolExecutor()作为执行器:
未来=执行者提交(λx:x+1,1)
return wait asyncio.wrap_future(未来)
打印(asyncio.run(my_async()))
在您的代码中,只需将
rs=future.result()
更改为rs=wait asyncio.wrap_future(future)
并使整个函数async
。这应该会很神奇,祝您好运!:)请更好地解释。代码不一致,即调用与函数名不匹配我更新了函数名。问题是,即使FastAPI使用asyncio,我也在线程池中执行包装。步骤2中的处理程序仍然会阻塞步骤3中的处理程序。然而,步骤3从不涉及任何数据库操作…async
用于协作并发。使用阻塞、正则函数是不合作的。因此,简单的答案是“不要使用阻塞函数”。你到底在找什么?这能回答你的问题吗?不它与睡眠无关,我已经使用了asyncio.sleep。问题是数据库锁导致异步函数挂起,另一个异步请求被阻止。。。这不是我所期望的。。。
INSERT INTO [dbo].[KVStore] VALUES ('1', '1', 0)
begin tran
SET TRANSACTION ISOLATION LEVEL Serializable
SELECT * FROM [dbo].[KVStore]
def kv_delete_by_key_2_sql():
conn = pytds.connect(dsn='192.168.0.1', database=cfg.kvStore_db, user=cfg.kvStore_uid,
password=cfg.kvStore_upwd, port=1435, autocommit=True)
engine = conn.cursor()
try:
sql = "delete KVStore; commit"
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(engine.execute, sql)
rs = future.result()
j = {
'success': True,
'rowcount': rs.rowcount
}
return jsonable_encoder(j)
except Exception as exn:
j = {
'success': False,
'reason': exn_handle(exn)
}
return jsonable_encoder(j)
@app.post("/kvStore/delete")
async def kv_delete(request: Request, type_: Optional[str] = Query(None, max_length=50)):
request_data = await request.json()
return kv_delete_by_key_2_sql()
async def hangit0(request: Request, t: int = Query(0)):
print(t, datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
await asyncio.sleep(t)
print(t, datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
j = {
'success': True
}
return jsonable_encoder(j)
@app.get("/kvStore/hangit/")
async def hangit(request: Request, t: int = Query(0)):
return await hangit0(request, t)