Why 'NoReturn' type exists in Python

Redowan Delowar February 21, 2022
Source

Technically, the type of None in Python is NoneType. However, you'll rarely see types.NoneType being used in the wild as the community has pretty much adopted None to denote the type of the None singleton. This usage is also documented in PEP-484.

Whenever a callable doesn't return anything, you usually annotate it as follows:

But sometimes a callable raises an exception and never gets the chance to return anything. Consider this example:

This semantically makes sense and if you run Mypy against the snippet, it won't complain. However, there's one difference between a callable that returns an implicit None vs one that raises an exception. In the latter case, if you run any code after calling the callable, that code won't be reachable. But Mypy doesn't statically catch that or warn you about the potential dead code. This is apparently fine by the type checker:

NoReturn type can be used in cases like this to warn us about potential dead code ahead. To utilize it, you'd type the above snippet like this:

Notice, that I changed the return type of the raise_verbose_type_error function to typing.NoReturn. Now, if you run Mypy against the snippet with the --warn-unreachable flag, it'll complain:

More practical examples

Callables containing infinite loops

Mypy will warn us about the dead code.

Another case where NoReturn can be useful, is to type callables with while True loops. This is common in webservers:

Callables that invoke 'sys.exit()', 'os._exit()', 'os.execvp()', etc

Both sys.exit() and os._exit() do similar things. The former function raises the SystemExit() exception and exits the program without printing any stacktrace or whatsoever. On the other hand, the latter function exits the process immediately without letting the interpreter run any cleanup code. Prefer sys.exit() over os._exit().

The os.execvp() function execute a new program, replacing the current process. It never returns. Here's how you'd type the callables that call these functions:

Further reading

Discussion in the ATmosphere

Loading comments...