A static type analyzer for Python code

User guide
Developer guide
Error classes
Supported features
Mailing list
File a bug

View the Project on GitHub google/pytype

Hosted on GitHub Pages — Theme by orderedlist


How is pytype different from other type checkers?

pytype has the ability to infer types for unannotated code. For more information, check out:

Can I find out what pytype thinks the type of my expression is?

Yes, insert reveal_type(expr) as a statement inside your code. This will cause pytype to emit an error that will describe the type of expr.

How do I reference a type from within its definition? (Forward References)

To reference a type from within its definition (e.g. when a method’s return type is an instance of the class to which the method belongs), specify the type as a string. This will be resolved later by PyType. For example:

class Person(object):
  def CreatePerson(name: str) -> 'Person':

I’m dynamically populating a class / module using setattr or by modifying locals() / globals(). Now pytype complains about missing attributes or module members. How do I fix this?

Add _HAS_DYNAMIC_ATTRIBUTES = True to your class or module.

Why didn’t pytype catch that my program (might) pass an invalid argument to a function?

pytype accepts a function call if there’s at least one argument combination that works. For example,

def f(x: float):
  return x
f(random.random() or 'foo')

is not considered an error, because f() works for float. I.e., the str argument isn’t considered. (This will change at some point in the future.) Note that this is different to attribute checking, where e.g.

(random.random() or 'foo').as_integer_ratio()

will indeed result in a type error.

How do I declare that something can be either byte string or unicode?

Using typing.Text if it is conceptually a text object, typing.Union[bytes, typing.Text] otherwise. See the style guide for more information.

I’m trying to use a mixin, but pytype raises errors about it. What should I do?

This happens when a mixin expects the classes it is mixed into to define particular functions. Let’s say we have a LoggerMixin class that expects a name method to be used in the log message:

class LoggerMixin:
  ...  # Other initialization.
  def log(self, msg: str):
    self._log.print(f'{}: {msg}')

When pytype checks LoggerMixin, it will raise an error that LoggerMixin has no method name. The solution is to make the mixin class have all the methods it needs.

One way to do this is to create an abstract base class that defines the expected API for the mixin:

import abc
class LoggerMixinInterface(metaclass=abc.ABCMeta):
  def name(self) -> str:
    raise NotImplementedError

class LoggerMixin(LoggerMixinInterface):
  ...  # Other initialization
  def log(self, msg: str):
    self._log.print(f'{}: {msg}')

class Person(LoggerMixinInterface):
  ...  # Other initialization
  def name(self):
    return self._name

With this setup, pytype won’t complain about, and it’s clear that LoggerMixin should only be mixed into classes that implement name.

Why is pytype taking so long?

If pytype is taking a long time on a file, the easiest workaround is to disable it with a skip-file directive. Otherwise, there are a few things you can try to speed up the analysis:

How do I disable all pytype checks for a particular file?

You can use

# pytype: skip-file

at the start of the file to disable all checking for a particular file, while still checking the rest of the blaze target that includes it.

How do I disable all pytype checks for a particular import?

You can use

from typing import Any
import foo  # type: Any

to disable checking for module foo. Note that pytype will still verify that foo is present among your target’s dependencies. To disable that check as well, replace # type: Any with # type: ignore.

How do I write code that is seen by pytype but ignored at runtime?

You can nest it inside an if typing.TYPE_CHECKING: block. This is occasionally needed to, for instance, conditionally import a module that is only used to provide type annotations.

Note that regardless of whether you use TYPE_CHECKING, if you’re using a build system, you’ll need to list all modules you import as dependencies of your target. That can lead to cycles in your build graph. Typically, that means that, short of rearranging your source tree, you won’t be able to annotate with that specific type. You can typically work around the “inexpressible” type by inserting Any where you would have used it. See the style guide for more information.

How do I silence overzealous pytype errors when adding multiple types to a dict (or list, set, etc.)?

A common pattern is to use a dictionary as a container for values of many types, for example:

    "slot1": Class1,
    "slot2": Class2,

This will often cause pytype to produce errors for any operation that is not valid on all of the types. To fix this, annotate the value type as Any:

MY_REGISTRY: Dict[str, Any] = {

Note that if you modify the dictionary in a different scope from the one in which it is defined, you may need to re-annotate it at the modification site to indicate to pytype that you are intentionally doing something it deems unsafe.