Starts the `IOLoop`, runs the given function, and stops the loop. The function must return either an awaitable object or ``None``. If the function returns an awaitable object, the `IOLoop` will run until the awaitable is resolved (and `run_sync()` will return the awa
(self, func: Callable, timeout: Optional[float] = None)
| 460 | raise NotImplementedError() |
| 461 | |
| 462 | def run_sync(self, func: Callable, timeout: Optional[float] = None) -> Any: |
| 463 | """Starts the `IOLoop`, runs the given function, and stops the loop. |
| 464 | |
| 465 | The function must return either an awaitable object or |
| 466 | ``None``. If the function returns an awaitable object, the |
| 467 | `IOLoop` will run until the awaitable is resolved (and |
| 468 | `run_sync()` will return the awaitable's result). If it raises |
| 469 | an exception, the `IOLoop` will stop and the exception will be |
| 470 | re-raised to the caller. |
| 471 | |
| 472 | The keyword-only argument ``timeout`` may be used to set |
| 473 | a maximum duration for the function. If the timeout expires, |
| 474 | a `asyncio.TimeoutError` is raised. |
| 475 | |
| 476 | This method is useful to allow asynchronous calls in a |
| 477 | ``main()`` function:: |
| 478 | |
| 479 | async def main(): |
| 480 | # do stuff... |
| 481 | |
| 482 | if __name__ == '__main__': |
| 483 | IOLoop.current().run_sync(main) |
| 484 | |
| 485 | .. versionchanged:: 4.3 |
| 486 | Returning a non-``None``, non-awaitable value is now an error. |
| 487 | |
| 488 | .. versionchanged:: 5.0 |
| 489 | If a timeout occurs, the ``func`` coroutine will be cancelled. |
| 490 | |
| 491 | .. versionchanged:: 6.2 |
| 492 | ``tornado.util.TimeoutError`` is now an alias to ``asyncio.TimeoutError``. |
| 493 | """ |
| 494 | if typing.TYPE_CHECKING: |
| 495 | FutureCell = TypedDict( # noqa: F841 |
| 496 | "FutureCell", {"future": Optional[Future], "timeout_called": bool} |
| 497 | ) |
| 498 | future_cell = {"future": None, "timeout_called": False} # type: FutureCell |
| 499 | |
| 500 | def run() -> None: |
| 501 | try: |
| 502 | result = func() |
| 503 | if result is not None: |
| 504 | from tornado.gen import convert_yielded |
| 505 | |
| 506 | result = convert_yielded(result) |
| 507 | except Exception: |
| 508 | fut = Future() # type: Future[Any] |
| 509 | future_cell["future"] = fut |
| 510 | future_set_exc_info(fut, sys.exc_info()) |
| 511 | else: |
| 512 | if is_future(result): |
| 513 | future_cell["future"] = result |
| 514 | else: |
| 515 | fut = Future() |
| 516 | future_cell["future"] = fut |
| 517 | fut.set_result(result) |
| 518 | assert future_cell["future"] is not None |
| 519 | self.add_future(future_cell["future"], lambda future: self.stop()) |