8

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

以trio 网站上的这个例子为例:

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. 您将如何捕获返回值以便我可以打印它们?

4

2 回答 2

11

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

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

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

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"])

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

于 2018-07-28T05:21:31.440 回答
1

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

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

于 2018-07-28T05:02:47.687 回答