Захватить возвращаемое значение из объектов питомника
При использовании трио и nursery
объекты, как вы захватываете любое значение, которое было возвращено из метода?
Возьмите этот пример с сайта трио:
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
, Как бы вы захватили возвращаемое значение, чтобы я мог распечатать их?
2 ответа
В настоящее время нет встроенного механизма для этого. Главным образом потому, что мы не выяснили, как бы мы хотели, чтобы это работало, поэтому, если у вас есть предложения, которые будут полезны:-).
Дело в том, что с обычными функциями есть одно очевидное место для доступа к возвращаемому значению - вызывающий ожидает, поэтому вы вручаете им возвращаемое значение, готово. При одновременных функциях вызывающая сторона не ждет, поэтому вам также нужно каким-то образом указать, куда ее возвращать, когда возвращать, если есть несколько функций, вы должны отслеживать, какая из них возвращает значение, и т.д. на. Это не такая простая концепция.
Что вы хотите сделать с возвращаемыми значениями? Вы хотите, скажем, напечатать их сразу, когда каждая функция вернется? В таком случае проще всего сделать это прямо из задач:
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
/ except
вокруг каждой отдельной функции, или outcome
библиотека. Или когда каждая операция заканчивается, вы можете поместить ее возвращаемое значение в trio.Queue
, так что другая задача может обработать результаты по мере их завершения. Но, надеюсь, это даст вам хорошую отправную точку:-)
В этом случае просто создайте массивы в родительском элементе и передайте каждый из них нуждающемуся дочернему элементу.
В более общем случае, передайте объект задачам; они могут установить атрибут на него. Вы также можете добавить Event
так что родитель может ждать результатов, которые будут доступны.