Wait for multiple asynchronous futures in parallel. Since Tornado 6.0, this function is exactly the same as `multi`. .. versionadded:: 4.0 .. versionchanged:: 4.2 If multiple ``Futures`` fail, any exceptions after the first (which is raised) will be logged. Added the ``q
(
children: Union[Sequence[_Yieldable], Mapping[Any, _Yieldable]],
quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),
)
| 506 | |
| 507 | |
| 508 | def multi_future( |
| 509 | children: Union[Sequence[_Yieldable], Mapping[Any, _Yieldable]], |
| 510 | quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (), |
| 511 | ) -> "Union[Future[List], Future[Dict]]": |
| 512 | """Wait for multiple asynchronous futures in parallel. |
| 513 | |
| 514 | Since Tornado 6.0, this function is exactly the same as `multi`. |
| 515 | |
| 516 | .. versionadded:: 4.0 |
| 517 | |
| 518 | .. versionchanged:: 4.2 |
| 519 | If multiple ``Futures`` fail, any exceptions after the first (which is |
| 520 | raised) will be logged. Added the ``quiet_exceptions`` |
| 521 | argument to suppress this logging for selected exception types. |
| 522 | |
| 523 | .. deprecated:: 4.3 |
| 524 | Use `multi` instead. |
| 525 | """ |
| 526 | if isinstance(children, dict): |
| 527 | keys = list(children.keys()) # type: Optional[List] |
| 528 | children_seq = children.values() # type: Iterable |
| 529 | else: |
| 530 | keys = None |
| 531 | children_seq = children |
| 532 | children_futs = list(map(convert_yielded, children_seq)) |
| 533 | assert all(is_future(i) or isinstance(i, _NullFuture) for i in children_futs) |
| 534 | unfinished_children = set(children_futs) |
| 535 | |
| 536 | future = _create_future() |
| 537 | if not children_futs: |
| 538 | future_set_result_unless_cancelled(future, {} if keys is not None else []) |
| 539 | |
| 540 | def callback(fut: Future) -> None: |
| 541 | unfinished_children.remove(fut) |
| 542 | if not unfinished_children: |
| 543 | result_list = [] |
| 544 | for f in children_futs: |
| 545 | try: |
| 546 | result_list.append(f.result()) |
| 547 | except Exception as e: |
| 548 | if future.done(): |
| 549 | if not isinstance(e, quiet_exceptions): |
| 550 | app_log.error( |
| 551 | "Multiple exceptions in yield list", exc_info=True |
| 552 | ) |
| 553 | else: |
| 554 | future_set_exc_info(future, sys.exc_info()) |
| 555 | if not future.done(): |
| 556 | if keys is not None: |
| 557 | future_set_result_unless_cancelled( |
| 558 | future, dict(zip(keys, result_list)) |
| 559 | ) |
| 560 | else: |
| 561 | future_set_result_unless_cancelled(future, result_list) |
| 562 | |
| 563 | listening = set() # type: Set[Future] |
| 564 | for f in children_futs: |
| 565 | if f not in listening: |
no test coverage detected