diff --git a/tests/test_main.py b/tests/test_main.py index b520f27dd..3db336472 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -102,7 +102,9 @@ def test_run_match_config_params() -> None: if key not in ("self", "timeout_notify", "callback_notify") } run_params = { - key: repr(value) for key, value in inspect.signature(run).parameters.items() if key not in ("app_dir",) + key: repr(value) + for key, value in inspect.signature(run).parameters.items() + if key not in ("app_dir", "suppress_ki") } assert config_params == run_params diff --git a/uvicorn/main.py b/uvicorn/main.py index 41e9ec84e..c3881ebc5 100644 --- a/uvicorn/main.py +++ b/uvicorn/main.py @@ -507,6 +507,7 @@ def run( app_dir: str | None = None, factory: bool = False, h11_max_incomplete_event_size: int | None = None, + suppress_ki: bool = False, ) -> None: if app_dir is not None: sys.path.insert(0, app_dir) @@ -575,6 +576,12 @@ def run( Multiprocess(config, target=server.run, sockets=[sock]).run() else: server.run() + except KeyboardInterrupt: + # KI is received deep inside asyncio and comes with a noisy traceback + # suppress it or raise a new KI here to shorten the traceback + if suppress_ki: + return + raise KeyboardInterrupt("quit uvicorn") from None finally: if config.uds and os.path.exists(config.uds): os.remove(config.uds) # pragma: py-win32