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