Packages installed with pip can declare that they support type checking, either by including type information inline or by providing separate stub packages.
PEP 561 packages
PEP 561 specifies how packages can declare type checking support.
There are two types:
Packages with type hints in the source code: # aiohttp includes type hints
from aiohttp import ClientSession
async def fetch ( url : str ) -> str :
async with ClientSession() as session:
async with session.get(url) as response:
return await response.text()
Install normally: Separate packages providing only stubs: # requests doesn't include types, use stub package
import requests
def fetch ( url : str ) -> str :
response = requests.get(url)
return response.text
Install stub package: pip install types-requests
Using typed packages
Mypy automatically finds and uses installed packages that support type checking:
Install type stubs if needed
For packages without inline types: pip install types-requests
Run mypy
Mypy automatically finds types in the installed packages.
Packages must be installed in the same Python environment where you run mypy.
Finding stub packages
Manual installation
Stub packages usually follow the naming convention types-<package>:
pip install types-requests
pip install types-redis
pip install types-PyYAML
pip install types-toml
Automatic installation
Mypy can suggest and install missing stubs:
# Discover missing stubs
mypy --install-types myproject
# Install non-interactively (for CI)
mypy --install-types --non-interactive myproject
This will:
Run mypy on your code
Detect missing type stubs
Suggest stub packages to install
Optionally install them automatically
Stub package versions
Stub packages often use newer type system features. Pin versions if using older mypy: # requirements-dev.txt
mypy==1.8.0
types-requests==2.31.0.6
types-redis==4.6.0.11
Version compatibility
Stub versions usually track the library version:
# For requests 2.31.x
pip install types-requests==2.31. *
But stub updates may require newer mypy:
error: Unsupported type hint (requires Python 3.10+)
Solution: Pin both mypy and stub versions.
Typeshed stubs
Mypy includes typeshed , which provides:
Python standard library stubs
Third-party library stubs (deprecated - now use separate packages)
Standard library
Built-in and standard library modules are always typed:
import json
import pathlib
from typing import Any
data: dict[ str , Any] = json.loads( '{"key": "value"}' )
path: pathlib.Path = pathlib.Path( "/tmp/file.txt" )
No installation needed - typeshed is bundled with mypy.
Using different Python environments
If packages are installed in a different environment:
Option 1: Point to the Python executable
mypy --python-executable /path/to/venv/bin/python myproject
Mypy will use that environment’s packages.
Option 2: Install in mypy’s environment
# Activate mypy's environment
source venv/bin/activate
# Install packages
pip install aiohttp types-requests
# Run mypy
mypy myproject
Disabling site-packages
To ignore all installed packages:
mypy --no-site-packages myproject
Or in configuration:
[mypy]
no_site_packages = True
Useful when you want complete control over type checking.
Creating typed packages
To make your package support type checking:
Inline typed package
Add type hints to code
# mypackage/core.py
def process ( data : str ) -> dict[ str , int ]:
return { "length" : len (data)}
Add py.typed marker
This tells mypy the package includes type information.
Include in package data
# setup.py
from setuptools import setup
setup(
name = "mypackage" ,
packages = [ "mypackage" ],
package_data = { "mypackage" : [ "py.typed" ]},
)
Or in pyproject.toml: [ tool . setuptools . package-data ]
mypackage = [ "py.typed" ]
Stub-only package
For packages you don’t maintain:
Create stub package structure
types-mypackage/
├── setup.py
└── mypackage-stubs/
├── __init__.pyi
├── core.pyi
└── py.typed
Write stubs
# mypackage-stubs/core.pyi
def process ( data : str ) -> dict[ str , int ]: ...
Configure setup.py
# setup.py
from setuptools import setup
setup(
name = "types-mypackage" ,
version = "1.0.0" ,
packages = [ "mypackage-stubs" ],
package_data = { "mypackage-stubs" : [ "*.pyi" , "py.typed" ]},
)
Stub packages use the -stubs suffix in the package directory name, but types- prefix for the distribution name.
When a package lacks types:
Ignore missing imports
[mypy-untyped_package.*]
ignore_missing_imports = True
This silences errors but provides no type checking for the package.
Create local stubs
Create stubs in your project:
myproject/
├── stubs/
│ └── untyped_package/
│ ├── __init__.pyi
│ └── module.pyi
└── myproject/
└── main.py
Configure MYPYPATH:
Contribute to typeshed
Create stubs and contribute to typeshed :
Fork typeshed
Add stubs in stubs/packagename/
Add METADATA.toml
Submit pull request
Configuration examples
Using typed packages
# mypy.ini
[mypy]
python_version = 3.10
# Automatically find installed packages
no_site_packages = False # Default
# Warn about missing stubs
warn_missing_imports = True
Ignoring untyped packages
[mypy]
# Strict checking
strict = True
# But ignore specific untyped packages
[mypy-legacy_package.*]
ignore_missing_imports = True
[mypy-another_untyped.*]
ignore_missing_imports = True
Different environments
[mypy]
# Point to production environment
python_executable = /usr/bin/python3.10
Troubleshooting
Stubs not found
Check package installation:
Verify mypy finds them:
mypy --verbose myproject 2>&1 | grep "site-packages"
Wrong stub version
Update stub package:
pip install --upgrade types-requests
If both inline types and stubs exist:
Inline types (package’s .py files) take precedence
Separate stub package is ignored
Remove stub package if the main package now has inline types:
pip uninstall types-requests
Cannot use MYPYPATH for stubs
Stub-only packages must be installed - they cannot be used via MYPYPATH: # This won't work
export MYPYPATH = / path / to / types-requests
# Must install instead
pip install types-requests
Popular stub packages
Commonly used stub packages:
# Web frameworks
pip install types-Flask
pip install types-requests
# Databases
pip install types-redis
pip install types-pymongo
# Data formats
pip install types-PyYAML
pip install types-toml
# Testing
pip install types-pytest
# Cloud services
pip install boto3-stubs[essential]
Use mypy --install-types to automatically discover and install needed stub packages.
Best practices
Pin versions Pin both mypy and stub package versions in requirements
Check CI environment Ensure CI installs the same packages as local development
Contribute stubs Share stubs with typeshed to help the community
Update regularly Keep stub packages updated as libraries evolve
Starting in mypy 0.900, most third-party stubs are separate packages. This allows independent versioning and faster updates.