基本上,我有与此类似的同步代码:
def f(.):
...
def call(.):
..Some sync code..
try:
resp = f(..)
...some more transformations of resp...
return ..
except:
..Some error handling..
async def af(.):
...
基本上,我想动态更改call
的代码,以便它可以调用并等待af
函数而不是f
。有没有解决的办法?我在github上发现了syncit
,但对我来说这并不是一个解决方案,因为您必须先重新编写代码以进行异步处理,然后再降级以进行同步。任何帮助将不胜感激。
答案 0 :(得分:1)
在asyncio
世界中,每个协程都可以在其他协程内部执行(使用await
),也可以通过事件循环阻塞调用(执行run_until_complete()
)执行。
您不能在常规函数中等待协程,因为此函数的调用将被阻塞,而等待协程需要阻塞事件循环执行。 asyncio
就是这样设计的。
如果您知道call()
函数被阻塞并且可以访问f()
实现,可以在f()
运行事件循环中执行协程:
async def af(.):
...
def f(.):
loop = asyncio.get_event_loop()
return loop.run_until_complete(af())
def call(.):
..Some sync code..
try:
resp = f(..)
...some more transformations of resp...
return ..
except:
..Some error handling..
如果您无权访问f()
的实现,我相信您将无法更改call()
来等待协程(无需进行一些丑陋的猴子修补)。
我认为将call()
重写为异步是唯一的好选择。
答案 1 :(得分:0)
在这里,我已经使用trio
库将您的示例修改为可以正常运行的演示:
给出
# Sync code
def call(x, y):
"""Return an awaited result."""
try:
resp = f(x, y)
return resp
except ZeroDivisionError:
return "Caught an exception."
# Async code
async def af(x, y):
"""Return an async result."""
await trio.sleep(3)
return x / y
代码
def f(*args):
"""Return results from an async function."""
return trio.run(af, *args)
演示
call(0, 1)
# 0.0
call(1, 0)
# 'Caught an exception.'
给出同步代码call
,您可以在函数trio
中使用f
来调用异步函数。
另请参阅trio
docs和创建者N. Smith的Talk Python interview,以了解更多详细信息及其异步编程哲学。