[英]Future task attached to a different loop
I am trying to connect to mongodb in FastAPI.我正在尝试在 FastAPI 中连接到 mongodb。 I am repeatedly getting this exception.
我反复收到此异常。
File - main.py文件 - main.py
app = FastAPI(
title=config.PROJECT_NAME, docs_url="/api/docs", openapi_url="/api"
)
@app.get("/api/testing")
async def testit():
user_collection = readernetwork_db.get_collection("user_collection")
all_users = await user_collection.find_one({"email": "sample_email"})
print("all users --- ", all_users)
return all_users
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", reload=True, port=8888)
File - session.py文件 - session.py
import motor.motor_asyncio
from app.core import config
print("here we go again....")
client = motor.motor_asyncio.AsyncIOMotorClient(
config.MONGOATLAS_DATABASE_URI)
readernetwork_db = client.get_database("readernetwork")
Exception -:例外 -:
all_users = await user_collection.find_one({"email": "sample_email"})
RuntimeError: Task <Task pending name='Task-4' coro=<RequestResponseCycle.run_asgi() running at /usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py:389> cb=[set.discard()]> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.8/asyncio/futures.py:360]> attached to a different loop
I don't know where I am getting this wrong.我不知道我在哪里弄错了。 Should I specify a event loop to motor?
我应该为电机指定一个事件循环吗?
You can have mongodb motor
client in the global scope, but creating and closing it should be done inside an async function.您可以在全局 scope 中拥有
mongodb motor
客户端,但创建和关闭它应该在异步 function 中完成。 The most preferable way of doing that in startup
and shutdown
handler of the application.在应用程序的
startup
和shutdown
处理程序中执行此操作的最优选方式。 Like so:像这样:
# mongodb.py
from motor.motor_asyncio import AsyncIOMotorClient
db_client: AsyncIOMotorClient = None
async def get_db_client() -> AsyncIOMotorClient:
"""Return database client instance."""
return db_client
async def connect_db():
"""Create database connection."""
db_client = AsyncIOMotorClient(DB_URL)
async def close_db():
"""Close database connection."""
db_client.close()
# main.py
app = FastAPI(title=PROJECT_NAME)
...
app.add_event_handler("startup", connect_db)
app.add_event_handler("shutdown", close_db)
Without the need for using global... You can access the application state from the request given to any route.无需使用全局... 您可以从给任何路由的请求中访问应用程序 state。
#main.py
async def open_db() -> AsyncIOMotorClient:
app.state.mongodb = AsyncIOMotorClient(DB_URL)
async def close_db():
app.state.mongodb.close()
app.add_event_handler('startup', open_db)
app.add_event_handler('shutdown', close_db)
Within each request to a given route you will have access to the app state.在对给定路线的每个请求中,您将可以访问应用程序 state。 For example,
例如,
@app.route('/{username}')
async def index(request: Request, username: str):
user = await request.app.state.mongodb['auth']['users'].find_one({"username" : username})
You can even make it easier by doing something like this in your open_db function.您甚至可以通过在您的 open_db function 中执行类似的操作来使其更容易。 Specify a state value like 'users' to be a specific Collections instance.
将 state 值(如“用户”)指定为特定的 Collections 实例。
async def open_db() -> AsyncIOMotorClient:
app.state.mongodb = AsyncIOMotorClient(DB_URL)
app.state.users = app.state.mongodb['auth']['users']
Now you can just do this,现在你可以这样做,
@app.route('/{username}')
async def index(request: Request, username: str):
user = await request.app.state.users.find_one({"username" : username})
client = AsyncIOMotorClient()
client.get_io_loop = asyncio.get_event_loop
works for me.为我工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.