python无法使用HTTP请求从异步函数获取返回值

python无法使用HTTP请求从异步函数获取返回值,python,python-asyncio,fastapi,uvloop,Python,Python Asyncio,Fastapi,Uvloop,我正在尝试将flask应用程序重写为FastAPI,它使用uvloop作为基础。 当我在没有路由的情况下执行代码时,我看不到任何问题,并按预期执行。但在我添加路由并使用邮递员点击请求后抛出错误 > INFO: ('172.17.0.1', 42352) - "GET /api/v1/getpass HTTP/1.1" 500 > ERROR: Exception in ASGI application Traceback (most recent call > last):

我正在尝试将flask应用程序重写为FastAPI,它使用
uvloop
作为基础。 当我在没有路由的情况下执行代码时,我看不到任何问题,并按预期执行。但在我添加路由并使用邮递员点击请求后抛出错误

> INFO: ('172.17.0.1', 42352) - "GET /api/v1/getpass HTTP/1.1" 500
> ERROR: Exception in ASGI application Traceback (most recent call
> last):   File
> "/usr/local/lib/python3.6/site-packages/uvicorn/protocols/http/httptools_impl.py",
> line 375, in run_asgi
>     result = await app(self.scope, self.receive, self.send)   File "/usr/local/lib/python3.6/site-packages/starlette/applications.py",
> line 133, in __call__
>     await self.error_middleware(scope, receive, send)   File "/usr/local/lib/python3.6/site-packages/starlette/middleware/errors.py",
> line 177, in __call__
>     raise exc from None   File "/usr/local/lib/python3.6/site-packages/starlette/middleware/errors.py",
> line 155, in __call__
>     await self.app(scope, receive, _send)   File "/usr/local/lib/python3.6/site-packages/starlette/exceptions.py", line
> 73, in __call__
>     raise exc from None   File "/usr/local/lib/python3.6/site-packages/starlette/exceptions.py", line
> 62, in __call__
>     await self.app(scope, receive, sender)   File "/usr/local/lib/python3.6/site-packages/starlette/routing.py", line
> 590, in __call__
>     await route(scope, receive, send)   File "/usr/local/lib/python3.6/site-packages/starlette/routing.py", line
> 208, in __call__
>     await self.app(scope, receive, send)   File "/usr/local/lib/python3.6/site-packages/starlette/routing.py", line
> 41, in app
>     response = await func(request)   File "/usr/local/lib/python3.6/site-packages/fastapi/routing.py", line 111,
> in app
>     raw_response = await dependant.call(**values)   File "./iowait.py", line 51, in get_pvt
>     print(kpair) UnboundLocalError: local variable 'kpair' referenced before assignment
我的代码:

import random
import asyncio as aio

from fastapi import FastAPI
from pydantic import BaseModel


get_id = '/api/v1/getid'
get_pass = '/api/v1/getpass'
app = FastAPI()
key_pass_list = [
    {
        'uid' : 'uid1',
        'pass' : 'pass1'
    },
    {
        'uid' : 'uid2',
        'pass' : 'pass2'
    },
    {
        'uid' : 'uid3',
        'pass' : 'pass3'
    },
]
id_list = [_['uid'] for _ in key_pass_list]


class KeyDoc(BaseModel):
    uid : str


async def key_pass(uid):
    for keypair in key_pass_list:
        if keypair['uid'] == uid:
            return keypair
    return {uid: 'Key not Found'}


@app.get(get_pass)
async def get_pvt(key_doc: KeyDoc):
    uid = key_doc.uid
    print('uid :' + uid)

    try:
        myloop = aio.get_event_loop()
        kpair = myloop.run_until_complete(aio.wait([key_pass(uid)]))
        await kpair
    except Exception as err:
        print(err)

    print(kpair)
    return None


@app.get(get_id)
async def get_pub():
    return random.choice(id_list)


@app.get("/")
async def root():
    return {"message": "Test-AIO"}
注意
get\u id
/
路由在任何时候都可以工作,因为没有逻辑,它会在
get\u pass
请求中失败。
非常感谢您在这方面的任何帮助或指点

谢谢你这里有两件事。首先,使用
aio.get\u event\u loop()
会引发异常
此事件循环在
wait kpair
之前已经运行了
。您可以通过在
get\u pvt
中的第一个print语句下添加
kpair=None
来查看此行为。下面是如何使用
asyncio.wait
构造此文件的

@app.get(get_pass)
async def get_pvt(key_doc: KeyDoc):
    uid = key_doc.uid
    print('uid :' + uid)
    done = set()
    try:
        done, pending = await aio.wait([key_pass(uid)])
    except Exception as err:
        print(err)

    if done:
        for task in done:
            print(task.result())
    return None

这里有两件事。首先,使用
aio.get\u event\u loop()
会引发异常
此事件循环在
wait kpair
之前已经运行了
。您可以通过在
get\u pvt
中的第一个print语句下添加
kpair=None
来查看此行为。下面是如何使用
asyncio.wait
构造此文件的

@app.get(get_pass)
async def get_pvt(key_doc: KeyDoc):
    uid = key_doc.uid
    print('uid :' + uid)
    done = set()
    try:
        done, pending = await aio.wait([key_pass(uid)])
    except Exception as err:
        print(err)

    if done:
        for task in done:
            print(task.result())
    return None