Mypy daemon (mypy server)

Instead of running mypy as a command-line tool, you can also run it as a long-running daemon (server) process and use a command-line client to send type-checking requests to the server. This way mypy can perform type checking much faster, since program state cached from previous runs is kept in memory and doesn’t have to be read from the file system on each run. The server also uses finer-grained dependency tracking to reduce the amount of work that needs to be done.

If you have a large codebase to check, running mypy using the mypy daemon can be 10 or more times faster than the regular command-line mypy tool, especially if your workflow involves running mypy repeatedly after small edits – which is often a good idea, as this way you’ll find errors sooner.

Note

The command-line of interface of mypy daemon may change in future mypy releases.

Note

Each mypy daemon process supports one user and one set of source files, and it can only process one type checking request at a time. You can run multiple mypy daemon processes to type check multiple repositories.

Basic usage

The client utility dmypy is used to control the mypy daemon. Use dmypy run -- <flags> <files> to typecheck a set of files (or directories). This will launch the daemon if it is not running. You can use almost arbitrary mypy flags after --. The daemon will always run on the current host. Example:

dmypy run -- prog.py pkg/*.py

dmypy run will automatically restart the daemon if the configuration or mypy version changes.

The initial run will process all the code and may take a while to finish, but subsequent runs will be quick, especially if you’ve only changed a few files. (You can use remote caching to speed up the initial run. The speedup can be significant if you have a large codebase.)

Note

Mypy 0.780 added support for following imports in dmypy (enabled by default). This functionality is still experimental. You can use --follow-imports=skip or --follow-imports=error to fall back to the stable functionality. See Following imports for details on how these work.

Daemon client commands

While dmypy run is sufficient for most uses, some workflows (ones using remote caching, perhaps), require more precise control over the lifetime of the daemon process:

  • dmypy stop stops the daemon.
  • dmypy start -- <flags> starts the daemon but does not check any files. You can use almost arbitrary mypy flags after --.
  • dmypy restart -- <flags> restarts the daemon. The flags are the same as with dmypy start. This is equivalent to a stop command followed by a start.
  • Use dmypy run --timeout SECONDS -- <flags> (or start or restart) to automatically shut down the daemon after inactivity. By default, the daemon runs until it’s explicitly stopped.
  • dmypy check <files> checks a set of files using an already running daemon.
  • dmypy recheck checks the same set of files as the most recent check or recheck command. (You can also use the --update and --remove options to alter the set of files, and to define which files should be processed.)
  • dmypy status checks whether a daemon is running. It prints a diagnostic and exits with 0 if there is a running daemon.

Use dmypy --help for help on additional commands and command-line options not discussed here, and dmypy <command> --help for help on command-specific options.

Additional daemon flags

--status-file FILE

Use FILE as the status file for storing daemon runtime state. This is normally a JSON file that contains information about daemon process and connection. The default path is .dmypy.json in the current working directory.

--log-file FILE

Direct daemon stdout/stderr to FILE. This is useful for debugging daemon crashes, since the server traceback is not always printed by the client. This is available for the start, restart, and run commands.

--timeout TIMEOUT

Automatically shut down server after TIMEOUT seconds of inactivity. This is available for the start, restart, and run commands.

--update FILE

Re-check FILE, or add it to the set of files being checked (and check it). This option may be repeated, and it’s only available for the recheck command. By default, mypy finds and checks all files changed since the previous run and files that depend on them. However, if you use this option (and/or --remove), mypy assumes that only the explicitly specified files have changed. This is only useful to speed up mypy if you type check a very large number of files, and use an external, fast file system watcher, such as watchman or watchdog, to determine which files got edited or deleted. Note: This option is never required and is only available for performance tuning.

--remove FILE

Remove FILE from the set of files being checked. This option may be repeated. This is only available for the recheck command. See --update above for when this may be useful. Note: This option is never required and is only available for performance tuning.

--fswatcher-dump-file FILE

Collect information about the current internal file state. This is only available for the status command. This will dump JSON to FILE in the format {path: [modification_time, size, content_hash]}. This is useful for debugging the built-in file system watcher. Note: This is an internal flag and the format may change.

--perf-stats-file FILE

Write performance profiling information to FILE. This is only available for the check, recheck, and run commands.

Static inference of annotations

The mypy daemon supports (as an experimental feature) statically inferring draft function and method type annotations. Use dmypy suggest FUNCTION to generate a draft signature in the format (param_type_1, param_type_2, ...) -> ret_type (types are included for all arguments, including keyword-only arguments, *args and **kwargs).

This is a low-level feature intended to be used by editor integrations, IDEs, and other tools (for example, the mypy plugin for PyCharm), to automatically add annotations to source files, or to propose function signatures.

In this example, the function format_id() has no annotation:

def format_id(user):
    return "User: {}".format(user)

root = format_id(0)

dymypy suggest uses call sites, return statements, and other heuristics (such as looking for signatures in base classes) to infer that format_id() accepts an int argument and returns a str. Use dmypy suggest module.format_id to print the suggested signature for the function.

More generally, the target function may be specified in two ways:

  • By its fully qualified name, i.e. [package.]module.[class.]function.
  • By its location in a source file, i.e. /path/to/file.py:line. The path can be absolute or relative, and line can refer to any line number within the function body.

This command can also be used to find a more precise alternative for an existing, imprecise annotation with some Any types.

The following flags customize various aspects of the dmypy suggest command.

--json

Output the signature as JSON, so that PyAnnotate can read it and add the signature to the source file. Here is what the JSON looks like:

[{"func_name": "example.format_id",
  "line": 1,
  "path": "/absolute/path/to/example.py",
  "samples": 0,
  "signature": {"arg_types": ["int"], "return_type": "str"}}]
--no-errors

Only produce suggestions that cause no errors in the checked code. By default, mypy will try to find the most precise type, even if it causes some type errors.

--no-any

Only produce suggestions that don’t contain Any types. By default mypy proposes the most precise signature found, even if it contains Any types.

--flex-any FRACTION

Only allow some fraction of types in the suggested signature to be Any types. The fraction ranges from 0 (same as --no-any) to 1.

--try-text

Try also using unicode wherever str is inferred. This flag may be useful for annotating Python 2/3 straddling code.

--callsites

Only find call sites for a given function instead of suggesting a type. This will produce a list with line numbers and types of actual arguments for each call: /path/to/file.py:line: (arg_type_1, arg_type_2, ...).

--use-fixme NAME

Use a dummy name instead of plain Any for types that cannot be inferred. This may be useful to emphasize to a user that a given type couldn’t be inferred and needs to be entered manually.

--max-guesses NUMBER

Set the maximum number of types to try for a function (default: 64).

Limitations