- Python type checking with Visual Studio Code
- Configure Venv
- Windows setup
- Linux or MacOS setup
- Install Mypy
- Setup
- Add Gitlens extension
- First simple example
- Django example
- Conclusions
- How to enable Python type checking in VSCode
- Python Type Hint
- Features
- Settings
- Known Issues
- Installation
- Mypy extension for VS Code
- Configuration
- Note for users upgrading from an older version
- License
Python type checking with Visual Studio Code
When working in a team, it’s important to establish a set of best practices that allows all the developers, old and new, to be productive while reducing the number of bugs and time required to understand a block of code. If you are working with other developers and need to be explicit with function signatures and variables, using static typed languages can be a good choice for your project. Since Python 3, you can add static types, but the IDE or code editor does not display any errors if you assign the incorrect value to a variable. In this tutorial, we will set up Python to behave like a static typed languages. We will configure real-time static types checking in VS Code for Python projects. I prefer that the setup only show errors when you explicitly add the type of variable or function parameter in your code, while still allowing for normal variables.
Configure Venv
Venv is a Python built-in tool for creating a virtual environment that isolates the project dependencies, so you can install dependencies only for that specific project without affecting other projects in your computer.
Windows setup
py -m venv venv .\venv\Scripts\activate
Linux or MacOS setup
python3 -m venv venv venv/bin/activate
Install Mypy
Next, install Mypy. This package checks types in your Python code and define a set of rules according to your needs.
Setup
Add Gitlens extension
"python.linting.mypyEnabled": true, "python.linting.mypyArgs": [ "--ignore-missing-imports", "--follow-imports=silent", "--show-column-numbers", "--allow-untyped-defs", "--allow-subclassing-any", "--allow-untyped-calls", "--strict" ] >
—strict : This option enables strict type checking. Although, it can be over strict in some cases. When you have existing code, and you don’t want to change it because you know it works. Furthermore, so many errors can be distracting for developers. The flags below customize this strict mode to make it less strict. —ignore-missing-imports : Suppresses error messages about unresolved imports. In Django, some imports can raise a warning without this flag. Only use it if your project contains warnings that you know aren’t a real problem. —follow-imports=silent : Turn off type checking in imported modules. Many libraries were not developed with static type checking in mind, so it’s better to suppress type checking in imported modules. —show-column-numbers : Shows column numbers in error messages. —allow-untyped-defs : Suppress errors if you have non-typed functions in Python. —allow-subclassing-any : Permits subclassing a value of type Any. Some frameworks can throw these errors with Mypy, therefore if you have them, add this line. —allow-untyped-calls : Allows you to invoke non-typed functions in your code. You should not have any issues by adding it gradually to your project with this setup. Mypy has a lot of options, feel free to try other configurations for your specific case.
First simple example
Create a example.py in the root of your project.
Add this code (yo lo dejaria hasta aqui) into that file.
def sum(n1: int, n2: int) -> int: return n1 + n2 def sub(n1, n2): return n1-n2 result = sum(1, 2.5) print(result) result = sub(1, 2.5) print(result)
As you can see in the image below, a lot of errors are displayed because sum expect two int parameters, but is given a float value. However, sub lacks a type definition, no errors are displayed. This is really powerful. Errors are displayed only in functions and variables that are required, and it will not interfere with your existing codebase.
Django example
Let’s try in a more complex scenario using a Django project. Django is a framework to build web applications. See the docs here. But don’t worry, there is no need to know it to follow this section. Keep in mind that Django is not a static typed Framework. Using only the —strict mode in settings.json will result in a lot of errors. If you configured the settings.json file as previously described, you shouldn’t have any issues. To create a new project:
pip install django django-admin startproject myapp cd myapp py manage.py startapp clients
from django.http import JsonResponse from django.shortcuts import render from urllib.request import Request from venv import create def createGreeting(name: str) -> str: return f'Hello name>. ' def getPower(n): x = 42 == 'no' return n**2 def index(request): message = createGreeting(3, 'asdf') message = createGreeting(100) message: int = 'asdf' message: str = 1234 n = getPower('asdf') return JsonResponse('message': message>)
Despite many errors appeared in clients.urls.py , the project is still running. Django imports and default code are fine because it will only check variables and functions that you manually type.
Conclusions
- If working in a team it reduces cognitive effort to understand how to use a piece of code.
- Increases productivity because the code documents itself.
- Improves code documentation and readability.
- Reduce redundant tests
- Constant real-time feedback.
- Reduces development errors
- It is customizable.
- Increases the complexity of your project.
- Many Python developers don’t like typing code.
- It is impossible to be certain that a function will return what it says.
- The less restrictive your configuration is, the fewer errors are displayed.
Use it to develop new libraries and complex modules that must be thoroughly tested. It’s not recommended for trying to add static typed to third-party libraries or legacy codebases (unless strictly necessary), because it could cause a lot of problems and time spent. Focus on the new code to write. Feel free to try with different configurations. In the long run, you and your team will be grateful for incorporating this tool into the workflow.
How to enable Python type checking in VSCode
Since version 3.5, Python now has support for type hints. This typing is a cool new feature allowing type checking across your code for more quality and also help when you are using some packages or call some functions your colleague did in a large codebase. In this article, we will see how to enable type IntelliSense and type checking analysis in Visual Studio Code editor.
First of all, you need to install the Microsoft extension Pylance. This extension provides a set of useful features powered with Pyright, the Microsoft static type checking tool.
With the extension installed and enabled, you should now have better IntelliSense with typing information when you are calling some package function for example. For the type checking analysis, it is not enabled by default, you need to configure it by yourself.
In your settings.json file, add a new line with the following setting:
"python.analysis.typeCheckingMode": "basic" >
The default value for this line is off meaning the static analysis is disabled. You have two other possible values which are:
- basic : basic type checking rules
- strict : All type checking rules at the highest error severity
If you test on the code below you should have a type error in VSCode now
# Wrong type between expected return type and the value type really returned by this function def wrong_return_type() -> str: return False
If you’re seeking solutions to a problem or need expert advice, I’m here to help! Don’t hesitate to book a call with me for a consulting session. Let’s discuss your situation and find the best solution together.
Python Type Hint
Provides type hint auto-completion for Python, with completion items for built-in types, classes and the typing module.
Features
- Provides type hint completion items for built-in types, estimated types and the typing module.
- Estimates the correct type to provide as a completion item.
- Can search Python files in the workspace for type estimation purposes.
Settings
Name | Description | Default |
---|---|---|
workspace.searchEnabled | (boolean) If enabled, other files in the workspace are searched when estimating types for a parameter. Disabling this will increase performance, but may reduce estimation accuracy. | true |
workspace.searchLimit | (number) The maximum number of files searched in a workspace search. Has no effect if workspace searching is disabled. | 10 |
Known Issues
- If workspace searching is enabled, a VSCode event (onDidOpen) is triggered when a file is searched. This causes other extensions that are listening to the event to analyse the same files, which can add the problems of those files to the Problems window. The only way to prevent this, for now, is by disabling the workspace search setting.
- The difference between function and class constructor calls when detecting types is determined by the first letter being upper case (unless the class or function is defined in the currently edited document).
Installation
The extension can found on the Visual Studio Marketplace.
Mypy extension for VS Code
This extension requires mypy to be installed on your system. To install mypy, run pip install mypy . There are other ways to install mypy, such as using pipx or your system’s package manager.
By default, this extension relies on having the dmypy executable available on your PATH. This should be the case if you installed mypy globally. To use a different mypy installation, set the mypy.dmypyExecutable setting.
Some people prefer to have mypy installed in each project’s virtual environment rather than in a global location. To do this, enable mypy.runUsingActiveInterpreter .
Configuration
To configure mypy, you can create a mypy.ini file in your workspace folder (or any of the default locations). See mypy configuration file. You can also specify a custom path to mypy.ini using the mypy.configFile setting.
To configure the mypy-vscode extension, use the following VS Code settings:
- mypy.targets : specify a list of target files or folders for mypy to analyze. By default the entire workspace folder is checked. You may prefer to use the files option in mypy.ini to specify which files mypy should analyze. In that case, you should set mypy.targets to an empty array ( [] ).
- mypy.dmypyExecutable : Path to dmypy (the mypy daemon). Either a full path or just a name (which must exist in your PATH). You can use substitutions: $ and ~ (home directory).
- mypy.runUsingActiveInterpreter : Use the active Python interpreter (selected in the Python extension) to run dmypy itself, instead of the mypy.dmypyExecutable setting. Note: your code is always checked against the active interpreter – this setting only controls the interpreter used to run dmypy itself.
- mypy.configFile : Mypy config file, relative to the workspace folder. If empty, search in the default locations. See https://mypy.readthedocs.io/en/latest/config_file.html.
Note for users upgrading from an older version
Previously, this extension used mypyls (the Mypy Language Server). However, this is no longer the case: the extension now uses the mypy daemon directly. See the change log for details. If you have previously installed mypyls , the extension will continue to use mypy from that same installation. If you want, you can uninstall mypyls and install mypy separately.
Also, in previous versions this extension automatically enabled mypy’s check_untyped_defs setting by default (see documentation). However, for consistency with mypy’s defaults, the extension no longer does this. To re-enable this option, use the mypy config file.
License
This project is made available under the MIT License.