【问题标题】:Extracting the function and arguments from a coroutine从协程中提取函数和参数
【发布时间】:2017-04-11 18:04:58
【问题描述】:

是否可以在python3.6中提取协程对象的函数和参数?

上下文:目前我有这样的事情:

async def func(*args):
    ...

ret = await remotely(func, x, y)

在后台,remotely 腌制 funcxy,scp 将其发送到不同的服务器,在那里它解开它们,执行 func(x,y),腌制结果,scp 将其返回,然后最后将其解压缩为ret

这个 API 让我觉得很反感,我宁愿拥有:

ret = await remotely(func(x, y))

如果我可以腌制func(x, y) 表示的协程对象,我可以这样做,但是当我尝试这样做时,我得到:

TypeError: can't pickle coroutine objects

所以我的另一个希望是我可以从f(x, y) 中提取fxy,因此提出了这个问题。

【问题讨论】:

    标签: python-asyncio python-3.6


    【解决方案1】:

    所以当你做ret = await remotely(func(x, y))时,你实际上是为func构造协程对象。幸运的是,您可以从协程对象中提取所需的信息,然后将其发送到远程执行。

    首先您可以使用__qualname__ 属性获取函数名称。这将为您提供完全限定的名称,即如果协程是嵌套的,它将为您提供函数的完整路径。

    接下来,您可以从协程的框架对象中提取参数值。

    这就是你的remote 函数的样子

    async def remote(cr):
        # Get the function name
        fname = cr.__qualname__
    
        # Get the argument values
        frame = cr.cr_frame
        args = frame.f_locals  # dict object
    
        result = await ...  # your scp stuff
    
        return result
    

    只有一个警告。您应该指出该功能只能以您发布的方式使用,即

    ret = await remotely(func(x, y))
    

    ...换句话说,协程应该是“新鲜的”,而不是中途执行(如果您将其直接传递给remote,这几乎是不可能的)。否则,f_locals 值可能包含在任何 awaits 之前定义的任何其他局部变量。

    【讨论】:

    • 谢谢你。我的同事实际上在我发帖后不久就设法解决了这个问题,并破解了dill 源代码,以便我们可以直接腌制协程对象。他独立提出了与您获取参数值相同的技术,但提出了一种不同的技术来获取没有__qualname__ 的函数。
    • 很高兴你解决了。也许您应该将工作解决方案作为单独的答案发布?
    • @dshin 我正在寻找相同问题的解决方案(我有同样的目的是为了定义更好的接口来定义发送到其他进程的函数)。莳萝不能转储协程对象 - 我试过了。您可以在某处发布您的方法吗?
    猜你喜欢
    • 2016-07-31
    • 2017-09-19
    • 2020-05-20
    • 1970-01-01
    • 2013-08-15
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多