从协程中提取函数和参数

dsh*_*hin 2 python-asyncio python-3.6

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

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

async def func(*args):
    ...

ret = await remotely(func, x, y)
Run Code Online (Sandbox Code Playgroud)

在幕后,remotelypickles func,xy, scp 的那个到不同的服务器,在那里它解压它们,执行func(x,y),pickles 结果, scp 的那个,最后将它解压到ret.

这个 API 对我来说很讨厌,我更喜欢:

ret = await remotely(func(x, y))
Run Code Online (Sandbox Code Playgroud)

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

TypeError: can't pickle coroutine objects
Run Code Online (Sandbox Code Playgroud)

所以我的备用的希望是,我可以提取fx以及yf(x, y),因此这个问题。

bag*_*rat 5

因此,当您这样做时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
Run Code Online (Sandbox Code Playgroud)

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

ret = await remotely(func(x, y))
Run Code Online (Sandbox Code Playgroud)

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