Skip to main content
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:
pip install aiohttp

Using typed packages

Mypy automatically finds and uses installed packages that support type checking:
1

Install the package

pip install aiohttp
2

Install type stubs if needed

For packages without inline types:
pip install types-requests
3

Run mypy

mypy myproject
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:
  1. Run mypy on your code
  2. Detect missing type stubs
  3. Suggest stub packages to install
  4. 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

1

Add type hints to code

# mypackage/core.py
def process(data: str) -> dict[str, int]:
    return {"length": len(data)}
2

Add py.typed marker

touch mypackage/py.typed
This tells mypy the package includes type information.
3

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:
1

Create stub package structure

types-mypackage/
├── setup.py
└── mypackage-stubs/
    ├── __init__.pyi
    ├── core.pyi
    └── py.typed
2

Write stubs

# mypackage-stubs/core.pyi
def process(data: str) -> dict[str, int]: ...
3

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.

Handling missing type information

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:
export MYPYPATH=./stubs

Contribute to typeshed

Create stubs and contribute to typeshed:
  1. Fork typeshed
  2. Add stubs in stubs/packagename/
  3. Add METADATA.toml
  4. 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:
pip list | grep types-
Verify mypy finds them:
mypy --verbose myproject 2>&1 | grep "site-packages"

Wrong stub version

Update stub package:
pip install --upgrade types-requests

Conflicting type information

If both inline types and stubs exist:
  1. Inline types (package’s .py files) take precedence
  2. 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
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.