我正在尝试从异步函数中的函数中获取。花了几个小时试图解决这个问题并遍历 Stack Overflow 以找到以前回答但无法帮助我找到解决自己问题的类似问题,我发现自己在这里。
很简单,我想使用 Web 浏览器和 Websockets 通过 Panoramisk 查询 Asterisk 管理界面。当用户连接到 websocket 服务器时,它运行 ws_handle 方法
async def ws_handle(websocket, path):
await register(websocket)
try:
async for message in websocket:
data = json.loads(message)
...
然后我想检索一些数据,然后交付给客户端。我遇到的问题是我发现我不能说
exts = yield from ExtensionStateList.get(AmiManager)
ExtensionStateList.get 函数的位置(大致)如下:
def get(AmiManager):
queues_details = yield from AmiManager.send_action(
{'Action': 'ExtensionStateList'})
...
val = {
'extensions': EXTENSIONS,
'parks': PARKS,
'paging': PAGING,
'confrences': CONFRENCES,
'apps': APPS,
'misc': MISC
}
return val
我在另一个与我的 websockets 服务器文件分开的测试文件中使用了同一个文件 ExtensionStateList.py,以非异步方法调用它,如前所示
exts = yield from ExtensionStateList.get(AmiManager)
没有问题,它用函数返回的值填充 exts。
我的研究使我像这样迭代它:
async for a in ExtensionStateList.get(AmiManager):
yield a
但我不知道如何使用它来填充我希望填充的变量。我试过这样:
exts = ''
async for a in ExtensionStatList.get(AmiManager):
exts = exts+a
只是被告知它不能将 AsyncIO.Future 加入字符串。我也试过换掉return val
a yield val
,再次没有运气。
显然,对我来说,这是我缺乏 Python 知识的一个缺点。我能做些什么?我在想也许我可以将 ExtensionStateList.get 更改为异步,但这会让我回到我现在所处的同一条船上?
此外
我继续翻遍 StackOverflow,发现了以下问题:
@types.coroutine 和 @asyncio.coroutine 装饰器有什么区别?
在我看来,也许如果我@asyncio.coroutine
在上面的行中添加ws_handle
,如下所示:
@asyncio.coroutine
async def ws_handle(websocket, path):
然后我将能够:
exts = yield from ExtensionStateList.get(AmiManager)
但是,我发现这不起作用,它告诉我不能从异步函数内部产生。我是否误解了我在这里阅读的内容?或者我可能没有正确实施它?我在正确的轨道上吗?
根据此处给出的答案:
'yield from' 异步函数 Python 3.6.5 aiohttp
我也尝试过像这样等待函数:
exts = await ExtensionStateList.get(AmiManager)
但是,Python 告诉我对象生成器不能用于 await 表达式。
此外
对于那些可能感兴趣的人,这就是我调用 ws_handle 函数的方式。在创建websocket服务器时调用,websocket服务器负责调度/调用?ws_handle 函数。
在我看来,它为每个连接的客户端调用一次此函数,并且此函数运行直到用户断开连接。
WebsocketServer = websockets.serve(ws_handle, host, port)
asyncio.get_event_loop().run_until_complete(WebsocketServer)
asyncio.get_event_loop().run_forever()
附录
是的,我再次添加更多。我修改了我的 ExtensionStateList.py,以便在调用 get 方法时,它按以下方式执行:
async def get(AmiManager):
val = await getInternal(AmiManager)
return val
@asyncio.coroutine
def getInternal(AmiManager):
我现在可以yield from
在 getInternal 函数中使用 internal ,这以前是我的 get 函数,我可以调用它并按以下方式接收日期:
exts = await ExtensionStateList.get(AmiManager)
我想我已经掌握了这一点,并且我看到了它们是如何以两种不同的方式来做几乎相同的事情。
感谢您为我指明正确的方向!