In the beginning, Python did not have typographical decorations. That fits with the overall goal of making the language fast and easy to use, with flexible object types that accommodate the twists and turns of writing code and help developers keep their code concise.
However, in recent years, Python has added support for type annotations, inspiring an entire software culture dedicated to checking Python types during development. Python doesn’t check types at run time, at least not yet. But by leveraging a good type checker, riding shotgun with you in your IDE of choice, you can use Python’s type annotations to rule out many common errors before they hit production.
In this article we will dive into four of the main type checking plugins for Python. They all follow roughly the same pattern, scanning the Python code with type annotations and providing feedback. But each offers its own useful additions to the basic concept.
mipy
Mypy was arguably the first static type checking system for Python, as work began in 2012 and it is still in active development. It’s essentially the blueprint for how third-party type-checking libraries work in Python, even if many others have since appeared and extended their features.
Mypy can be run standalone or from the command line, or it can work as part of an editor or IDE’s linter integration. Many editors and IDEs integrate Mypy; The Visual Studio Code Python extension can work directly with it. When run, Mypy generates reports on the consistency of your code based on the type of information you provide.
If your code does not include type annotations, Mypy will not perform the vast majority of your code checks. However, you can use Mypy to mark up code without annotations. This can be done with varying degrees of rigor depending on one’s needs.
If you are starting from scratch with a codebase and want a preemptively aggressive linting strategy, you can use the --strict
option to avoid any unwritten code. On the other hand, if you’re working with a legacy codebase that doesn’t have many type definitions, you can use more relaxed options, such as avoiding only untyped function definitions with --disallow-untyped-defs
while allowing other untyped code. And you can always use inline comments like # type: ignore
to prevent individual lines from being marked.
Mypy can make use of PEP 484 stub files when you want to use type hints for a module’s public interfaces. In addition to this, Mypy offers stubgen
, a tool that automatically generates stub files from existing code. For untyped code, the stubs use generic types, which you can then mark as needed.
pytipo
Pytype, created by Google, differs from the likes of Mypy in its use of inference rather than just writing descriptors. In other words, Pytype attempts to determine types by parsing the code stream, rather than strictly relying on type annotations.
Pytype errs on the side of leniency whenever it makes sense to do so. If you have an operation that works at runtime and doesn’t contradict any annotations, Pytype won’t complain. However, this means that some issues that should be flagged (eg, declaring a variable with a type at a point and then redefining it in the same context) go unnoticed. The documentation states that such things will not be allowed at some point in the future.
If you choose to add type annotations to your code, Pytype reveal_type
The function is especially useful. If you insert a statement in your code that says reveal_type(expr)
Pytype evaluates expr
and issues an alert describing its type.
Note that certain Pytype behaviors are controlled by adding attributes to the code itself. For example, if you want to prevent Pytype from complaining about missing attributes or dynamically configured module members, you should add the attribute _HAS_DYNAMIC_ATTRIBUTES = True
to the class or module in question, rather than setting some sort of pytype configuration metadata.
Pyright/Pylance
Pyright is Microsoft’s Python type checker, included as part of the Pylance extension for Visual Studio Code. If you’re already a VS Code user, the Pylance extension is the most convenient way to work with Pyright; just install and go. Pyright provides a good all-round type checking and code debugging experience, with many of the same conveniences and enhancements as previous Python analysis tools.
Like Pytype, Pyright can work with code bases that don’t have any data. In those cases, Pyright will do its best to infer what types are in play. So you can still get good results with Pytype on older codebases without type declarations. But you’ll get better results over time as you progressively add type annotations to your code.
Pyright is very flexible in ways that complement real-world Python project designs. As with other type checkers, Pyright can be configured on a per-project basis with a JSON-formatted configuration file in the project directory. Individual routes can be excluded (never checked) or ignored (errors and warnings suppressed) in the configuration file, and the options are very granular.
In VS Code, multi-rooted workspaces can each have their own pyright settings, in case different parts of the project need different linting settings. Similarly, you can define multiple “runtimes” within a project, each with their own import or venv paths.
Pyre
Created by developers at Facebook and Instagram, Pyre is actually two tools in one: a type checker (Pyre) and a static code analysis tool (Pysa). The two are designed to work hand in hand to provide a higher level of verification and analysis than other tools, although the user needs to do a bit of heavy lifting to get the most out of them.
Pyre takes a similar approach to Pytype and Mypy. Raw code is handled more leniently than written code, so you can start with a raw Python codebase and add annotations on a function-by-function and module-by-module basis. Activate “strict mode” on a module and Pyre will flag any missing annotations. Or you can make strict mode the default and opt out at the module level. Pyre will also work with stub files in .pyi format.
Pyre has a powerful feature for migrating codebases to a written format. He infer
The command line option ingests a file or directory, makes educated guesses about the types used, and applies the annotations to the files. However, you’ll want to make backup copies of your code first. (If you want to get information about the type of a run Python program, you can do it with another Facebook/Instagram project, MonkeyType).
While Pyre’s features echo those of the other packages detailed here, Pysa is unique. Pysa performs a “corruption scan” on code to identify potential security issues, drawing on a stream analysis library for certain software components and flagging code that appears to be vulnerable. Anything that touches that code will also be marked as contaminated, although you can specify components that sanitize the data and remove it from the contamination graph.
One drawback is that Pysa’s third-party component corruption analysis library is still small, so you may need to design your own model. But many of the corruption scans are for widely used software such as the Django web framework, SQL Alchemy ORM, and the Pandas data science library, not to mention scans for common file system problems.
How to do more with Python
Copyright © 2023 IDG Communications, Inc.
Be First to Comment