是否有Python方式在后台运行异步任务,类似于使用contextmanager?

时间:2018-09-04 01:01:11

标签: python async-await python-asyncio contextmanager

最近我想在后台运行其他任务的同时运行一些异步任务,但我认为代码不够 Pythonic

struct NodeLevel{
    int level;
    BinaryTreeNode * node;
    NodeLevel(int val, BinaryTreeNode * x) : level(val), node(x) {}  
};

class Solution {
public:
    vector<vector<int>> levelOrder(BinaryTreeNode* root) {
        queue<NodeLevel> q;
        rootLevel = NodeLevel(0, root);
        q.push(rootLevel);

        /*
        do some stuff with the queue 
        */
    }
};

所以我做了更多 Pythonic

task = asyncio.create_task(long_task())
await short_task()
await task

这样的东西已经存在了吗?如果不是这样,是否认为它比现有方法更像Pythonic或更不像Pythonic?

2 个答案:

答案 0 :(得分:2)

  

这样的东西已经存在了吗?

目前不行,但这是一个非常有用的主意。该概念的更一般版本将以TaskGroupCurio的现有技术启发而以Trio类的形式添加到Python 3.8。

我建议增强使用finally的实现,以保证即使在异常情况下也可以等待后台任务;例如:

@asynccontextmanager
async def run_in_background(coro):
    task = asyncio.create_task(coro)
    try:
        yield task
    finally:
        await task
  

如果不是这样,是否认为它比现有方法更具Python风格?

问题的这一部分显然是基于观点的,但是我想说上下文管理器更具有Python风格,因为它确保在离开该块时已经完成并等待后台任务。它还可以确保后台任务do not pass silently中的异常,这是异步代码中错误的常见来源。

答案 1 :(得分:0)

trio为苗圃对象提供了一种更好的方法:

async with trio.open_nursery() as nursery:
    nursery.start_soon(long_task())  # Task will run in background

    await short_task()
    # Wait for background tasks to finish