python中的async exec

问题描述 投票:3回答:3

我想在异步函数中调用exec并执行类似下面的代码(这是无效的):

import asyncio

async def f():
    await exec('x = 1\n' 'await asyncio.sleep(x)')

更确切地说,我希望能够在exec中运行的代码中等待未来。

怎么能实现这一目标?

python python-3.x exec python-asyncio
3个回答
2
投票

注意:F-strings仅在python 3.6+中受支持。对于旧版本,请使用%s.format()或经典的+连接。

async def execute(code):
    # Make an async function with the code and `exec` it
    exec(
        f'async def __ex(): ' +
        ''.join(f'\n {l}' for l in code.split('\n'))
    )

    # Get `__ex` from local variables, call it and return the result
    return await locals()['__ex']()

6
投票

你的问题是你试图等待None对象 - exec忽略其代码的返回值,并始终返回None。如果要执行并等待结果,则应使用eval-eval返回给定表达式的值。

你的代码应如下所示:

import asyncio

async def f():
    exec('x = 1')
    await eval('asyncio.sleep(x)')

loop = asyncio.get_event_loop()
loop.run_until_complete(f())
loop.close()

2
投票

感谢所有的建议。我发现这可以通过同步的greenlet完成,因为greenlets允许执行“顶级等待”:

import greenlet
import asyncio

class GreenAwait:
    def __init__(self, child):
        self.current = greenlet.getcurrent()
        self.value = None
        self.child = child

    def __call__(self, future):
        self.value = future
        self.current.switch()

    def __iter__(self):
        while self.value is not None:
            yield self.value
            self.value = None
            self.child.switch()

def gexec(code):
    child = greenlet.greenlet(exec)
    gawait = GreenAwait(child)
    child.switch(code, {'gawait': gawait})
    yield from gawait

async def aexec(code):
    green = greenlet.greenlet(gexec)
    gen = green.switch(code)
    for future in gen:
        await future

# modified asyncio example from Python docs
CODE = ('import asyncio\n'
        'import datetime\n'

        'async def display_date():\n'
        '    for i in range(5):\n'
        '        print(datetime.datetime.now())\n'
        '        await asyncio.sleep(1)\n')

def loop():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(aexec(CODE + 'gawait(display_date())'))
    loop.close()
© www.soinside.com 2019 - 2024. All rights reserved.