【问题标题】:Know within function if it was called synchronously or asynchronously知道函数内是同步调用还是异步调用
【发布时间】:2020-12-29 02:51:09
【问题描述】:

我想知道是否有人知道任何可以告诉我正在运行的函数是同步调用还是异步调用的神奇函数。长话短说,我想做以下事情:

def fsync():
    was_called_async() # >>> False

async fasync():
    was_called_async() # >>> True

fsync()
await fasync()

这听起来可能有点奇怪,我同意。原因是因为我正在尝试实现类似于functools.singledispatchmethod 的功能,但用于同步和异步方法。这需要使用装饰器,因此需要“等待内省”。我目前的工作方法here 按预期工作:

from toolbox.cofunc import cofunc
import asyncio
import time

@cofunc
def hello():
    time.sleep(0.01)
    return "hello sync world!"

@hello.register
async def _():
    await asyncio.sleep(0.01)
    return "hello async world!"

async def main():
    print(hello())        # >>> "hello sync world!"
    print(await hello())  # >>> "hello async world!"

asyncio.run(main())

但是,它使用了inspect 模块,我不想依赖它(获取上一帧并搜索await)。如果有人知道那将是可爱的替代方案。

【问题讨论】:

  • 您的答案绝对值得为您当前解决方案的纯粹创意点赞。 :) 但不幸的是,它工作起来太聪明了,不仅因为它使用检查,而且因为它需要访问 Python 源代码,所以它不适用于纯 pyc 代码,也不适用于 Cython。另外,我不确定它是否正确处理了多个调用,其中一些正在等待,而另一些则没有。
  • 当然,答案提供了为什么它不起作用的更直接的普通原因 - 在 Python 中,您等待一个可等待的对象(例如通过调用 async 函数或在 asyncio 中返回的协程对象任何一种未来),不一定是函数调用。换句话说,做x = foo(); await x 之类的事情或将协程对象存储在字典中只是为了稍后等待它是完全合法的,依此类推。
  • 几天后,我想我找到了解决方案:也就是说,没有。这个问题没有合适的解决方案。

标签: python asynchronous python-asyncio


【解决方案1】:

没有一个好方法可以做你正在寻找的事情。

“同步调用”或“异步调用”函数之间没有实际区别。无论哪种方式,该函数都只是被调用。

最接近区别的是调用者对返回值的处理,但即使寻找await 也是一个坏主意,因为像

await asyncio.gather(yourfunc(), something_else())

asyncio.run(yourfunc())

直觉上会被认为是“异步的”。

到目前为止,最可靠的选择是只有两个功能。

【讨论】:

  • 你关于调用异步函数的其他方法的观点是正确的,正是为什么我想知道这个问题——解析 ast 树以找到所有可能的方法调用异步函数(gatherrunrun_until_complete 等)会很痛苦。尽管如此,我还是感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 2021-03-17
相关资源
最近更新 更多