Let’s explore the two alternatives I suggested with aiohttp, which is a heavy package to import.
You can create an empty _typing_imports.py module, and a corresponding _typing_imports.pyi module, containing just:
import aiohttp as aiohttp
Elsewhere in your code, you can import your typing-only module:
from . import _typing_imports as _t # Let's shorten it too
async def fetch_some_data(value: _t.aiohttp.ClientSession) -> None: ...
This solution is slightly more involved, but it also has some benefits. In addition to avoiding the typing import, thus satisfying the motivation of this PEP:
- It approaches typing imports systematically, meaning:
- It makes the fact that the module you imported can only be used in (delayed) annotations explicit (without resorting to aliasing
aiohttpitself wherever it might be imported). - It makes guarding typing-only
aiohttpimports throughout your codebase unnecessary.
- It makes the fact that the module you imported can only be used in (delayed) annotations explicit (without resorting to aliasing
- It allows you to evaluate your
aiohttpannotations so that they can be used at runtime, e.g. by defining a module-level__getattr__in your_typing_imports.py:def __getattr__(name): if name == 'aiohttp': import aiohttp return aiohttp raise AttributeError(name) - It can be done today.