【问题标题】:Capture the return value from nursery objects从 Nursery 对象中捕获返回值
【发布时间】:2018-07-28 02:09:42
【问题描述】:

当使用 trio 和 nursery 对象时,如何捕获从方法返回的任何值?

以三重奏网站上的this 为例:

async def append_fruits():
    fruits = []
    fruits.append("Apple")
    fruits.append("Orange")
    return fruits

async def numbers():
    numbers = []
    numbers.append(1)
    numbers.append(2)
    return numbers

async def parent():
    async with trio.open_nursery() as nursery:
        nursery.start_soon(append_fruits)
        nursery.start_soon(numbers)

我对其进行了修改,以便每个方法都返回一个list。您将如何捕获返回值以便我可以打印它们?

【问题讨论】:

    标签: python-3.x python-trio


    【解决方案1】:

    目前,对此没有内置机制。主要是因为我们还没有弄清楚我们甚至希望它如何工作,所以如果你有一些有用的建议:-)。

    问题是,对于常规函数,只有一个明显的地方可以访问返回值——调用者正在等待,所以你把返回值交给他们,完成。对于并发函数,调用者不会等待,因此您还需要一些方法来指定将其返回到哪里、何时返回、如果有多个函数您必须跟踪哪个函数正在返回一个值,等等在。这不是一个简单的概念。

    你想对返回值做什么?例如,您想在每个函数返回时立即打印它们吗?在这种情况下,最简单的方法是直接从任务中完成:

    async def print_fruits():
        print(await fruits())
    
    async def print_numbers():
        print(await numbers())
    
    async with trio.open_nursery() as nursery:
        nursery.start_soon(print_fruits)
        nursery.start_soon(print_numbers)
    

    您甚至可以将其纳入辅助函数:

    async def call_then_print(fn):
        print(await fn())
    
    async with trio.open_nursery() as nursery:
        nursery.start_soon(call_then_print, fruits)
        nursery.start_soon(call_then_print, numbers)
    

    或者你想把它们放在一个数据结构中以便以后查看?

    results = {}
    
    async def store_fruits_in_results_dict():
        results["fruits"] = await fruits()
    
    async def store_numbers_in_results_dict():
        results["numbers"] = await numbers()
    
    async with trio.open_nursery() as nursery:
        nursery.start_soon(store_fruits_in_results_dict)
        nursery.start_soon(store_numbers_in_results_dict)
    
    # This is after the nursery block, so we know that the dict is fully filled in:
    print(results["fruits"])
    print(results["numbers"])
    

    您也可以想象这些更高级的版本——例如,有时当您并行运行大量任务时,您希望捕获异常,而不仅仅是返回值,这样即使其中一些任务失败,一些任务仍然可以成功。为此,您可以在每个单独的函数或outcome 库周围使用try/except。或者,当每个操作完成时,您可以将其返回值放入trio.Queue,以便另一个任务可以在结果完成时对其进行处理。但希望这能给你一个好的起点:-)

    【讨论】:

    • 任何 ETA 尚未确定,您什么时候能弄清楚?我的意思是你希望它如何工作?因为有一个简单的 future 保证在 Nursery 块之后作为修改后的 start_soon() 的返回值被填充,这对于三重奏功能的开始和巨大的好处是完全足够的。
    • +1,某种简单的trio.Future 对象在这里会非常有用。我猜基本上outcome.Outcome 是什么。
    • 有没有关于这个的未解决的问题?我想我希望每次调用start_soon 都会返回一个未来......顺便说一句,在我看来,托儿所只是带有额外保证的嵌套事件循环。
    【解决方案2】:

    在这种情况下,只需在父级中创建数组并将每个数组传递给需要它的子级。

    更一般地,将对象传递给任务;他们可以在上面设置一个属性。您还可以添加Event,以便家长可以等待结果可用。

    【讨论】:

      猜你喜欢
      • 2014-01-23
      • 2016-09-09
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多