Skip to content


Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or "duck") typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking.

You can use this cookiecutter template to create a python project with mypy already configured.


pip install mypy


Mypy configuration is saved in the mypy.ini file, and they don't yet support pyproject.toml.

File: mypy.ini

show_error_codes = True
follow_imports = silent
strict_optional = True
warn_redundant_casts = True
warn_unused_ignores = True
disallow_any_generics = True
check_untyped_defs = True
no_implicit_reexport = True
warn_unused_configs = True
disallow_subclassing_any = True
disallow_incomplete_defs = True
disallow_untyped_decorators = True
disallow_untyped_calls = True

# for strict mypy: (this is the tricky one :-))
disallow_untyped_defs = True

You can use it both with:

  • Pre-commit:

    File: .pre-commit-config.yaml

    - repo:
      rev: v0.782
      - name: Run mypy static analysis tool
        id: mypy
  • Github Actions:

    File: .github/workflows/lint.yml

    name: Lint
    on: [push, pull_request]
        runs-on: ubuntu-latest
        name: Mypy
        - uses: actions/checkout@v1
        - name: Set up Python 3.7
          uses: actions/setup-python@v1
            python-version: 3.7
        - name: Install Dependencies
          run: pip install mypy
        - name: mypy
          run: mypy

    Ignore one line

Add # type: ignore to the line you want to skip.


Module X has no attribute Y

If you're importing objects from your own module, you need to tell mypy that those objects are available. To do so in the of your module, list them under the __all__ variable.


from .model import Entity

__all__ = [

[W0707: Consider explicitly re-raising using the 'from'


The error can be raised by two cases.

  • An exception was raised, we were handling it, and something went wrong in the process of handling it.
  • An exception was raised, and we decided to replace it with a different exception that will make more sense to whoever called this code.
  self.connection, _ = self.sock.accept()
except socket.timeout as error:
  raise IPCException('The socket timed out') from error

The error bit at the end tells Python: The IPCException that we’re raising is just a friendlier version of the socket.timeout that we just caught.

When we run that code and reach that exception, the traceback is going to look like this:

Traceback (most recent call last):
  File "", line 19, in
    self.connection, _ = self.sock.accept()
  File "", line 7, in accept
    raise socket.timeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "", line 21, in
    raise IPCException('The socket timed out') from e
IPCException: The socket timed out

The The above exception was the direct cause of the following exception: part tells us that we are in the second case.

If you were dealing with the first one, the message between the two tracebacks would be:

During handling of the above exception, another exception occurred:



Last update: 2021-04-07