Visual Studio Code, or VS Code for short, is a free and open source code editor by Microsoft. You can use VS Code as a lightweight code editor to make quick changes, or you can configure it as an integrated development environment (IDE) through the use of third-party extensions. In this tutorial, you’re going to look at how to get the most out of VS Code for Python development.
During this tutorial, you’ll learn how you can configure, extend, and optimize VS Code for a more effective and productive Python development environment. After finishing this tutorial, you’ll have a variety of tools to help you be more productive using VS Code. It can be a powerful tool for rapid Python development.
In this tutorial, you’ll learn how to:
- Customize your user interface
- Run and monitor Python tests
- Lint and format your code automatically
- Leverage type annotations and Pylance to write code faster with higher accuracy
- Configure and utilize both local and remote debugging
- Set up data science tools
As usual, this tutorial is full of links, tips, and tricks to help you on your way.
If you haven’t already installed Visual Studio Code or the Python extension, you’ll need both for this tutorial. If you’re just getting started with VS Code, you might want to check out Jon Fincher’s tutorial on Python development in Visual Studio Code before continuing with this one.
Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Mastering the Visual Studio Code User Interface
By default, VS Code’s user interface is designed for everyone—whether you’re writing C++, doing front-end development with JavaScript and CSS, or using data science tools like Jupyter Notebooks. In this first section, you’ll explore how to tailor VS Code to support how you work.
Keyboard Shortcuts
For almost everything that you do in VS Code, you can do it directly from the keyboard. You can map all activities in VS Code, whether they’re built-in or provided via extensions, to a keyboard shortcut.
A small subset of built-in commands is already mapped in Keyboard Shortcuts. If you want to learn these default shortcuts, print out the PDF for Windows, macOS, or Linux and pin it next to your monitor.
As a Python developer, a lot of the commands you’ll use in Visual Studio Code are provided from extensions, similar to the Python extension that you already installed. These don’t come with shortcuts mapped by default, but you can configure them using VS Code’s Keyboard Shortcuts editor.
Using the Keyboard Shortcuts Editor
Open the Keyboard Shortcuts editor by going to File → Preferences → Keyboard Shortcuts or Code → Preferences → Keyboard Shortcuts on macOS:

In this editor, you can see a list of all the existing shortcuts along with their details:
- Command: The command or action to be run
- Keybinding: The sequence of keys to press to trigger this command, with a blank indicating that there’s no mapping
- When: Conditions that need to be met for this keybinding to work, with a minus sign (
-) indicating that there are no requirements - Source: Where this binding was configured, either defined by Default, User, or Extension, the last one indicating that you provided it by installing a keymap extension
To override an existing binding, right-click on the existing action and click Change Keybinding. To assign a keybinding to a command that has no binding, double-click on it. If the key sequence you press is already assigned to something else, VS Code will warn you with a link to see which commands are mapped to this keybinding.
As an example, type python create terminal in the search box at the top. If no results come up, make sure you have the Python extension installed. Press Enter to assign a keybinding, like Ctrl+Alt+T, and then hit Enter again.
To assign that shortcut to only work when you’re editing Python code, right-click on the shortcut and select Change When Expression. Enter the expression editorLangId == 'python':

There are more conditional operators to choose from if you need something more specific. Here are some examples to get you started:
- Use
resourceFilename == '__init__.py'when the file you’re editing is__init__.py - Use
editorLangId == 'python'when working with Python. If needed, you can also replace'python'with another language identifier. - Use
editorHasSelectionfor when you’re inside the editor.
Once you’ve configured this extension, open up a Python file in the editor to try it out by pressing your newly assigned keyboard shortcut Ctrl+Alt+T to open up a Python terminal.
Setting Up Keyboard Shortcuts for Commands From the Command Palette
You’ll refer to the Command Palette many times in this tutorial. Most of the functionality in VS Code is accessible through the UI from context menus, but you won’t find everything there. Anything that can be done in the core editor or via an extension is available in the Command Palette. You can get to the Command Palette by pressing one of these keyboard shortcuts:
- macOS: F1 or Cmd+Shift+P
- Windows or Linux: F1 or Ctrl+Shift+P
To run a command, type its descriptive name, like Python: Run All Tests. Once the Command Palette is up and the command you want is at the top of the menu, click the cog on the right to assign a keyboard shortcut:

Once you’ve started using the Command Palette regularly, you may find that there are five to ten commands you run really often. Assign some shortcuts to those commands to save yourself a few extra keystrokes.
Installing Keyboard Mappings From Other Editors
If you’ve been working in another editor or IDE for some time, you may have your usual keyboard shortcuts committed to muscle memory.
You’ll find helpful keyboard mappings in extensions for Vim, IntelliJ and PyCharm, Sublime Text, Notepad++, Emacs, and Atom.
If your previous editor isn’t on this list, you may find that someone else has created a mapping extension for you. Keymaps is a helpful category on the VS Code extension marketplace.
Once you’ve installed a keymap extension, you may also find additional options to customize it beyond the defaults. For example, you can use the Vim keymap extension to configure Vim features such as whether to start in insert mode.
Customizing the User Interface
The first things you should do when jumping into the driving seat of a car are to adjust the seat, adjust the rear-view mirror, and set the steering column to the right height. Code editors are no different. They come with a default layout that works okay for everyone but not especially well for anyone. You don’t want to stretch to reach the pedals. Let’s set up your VS Code environment to suit you and make it look great on the way.
First, the Activity Bar on the left-hand side of VS Code is the main navigation tool to switch between the Explorer view used to see your files, the Source Control view, the Search view, the Run and Debug view, and the Extensions view. You’re not limited to these options. Many extensions come with views that are hidden by default. Right-click on the Activity Bar to control which views you see:

You can also use this menu to hide any views that you never use. Keep in mind that you’re not limited to the views on the list. If there are some panels within a main view—for example, you can find some additional panels nested inside the Explorer view—you can drag them to the Activity Bar to create a permanent shortcut:

Use this feature for views that you use all the time.
Using Split Screens
Python’s style guide, PEP 8, leans toward short line lengths. For wide screens, this leaves a lot of unused screen space.
When you find yourself needing to switch between two or more files, use the split panel functionality to show many editor regions at once. You can access this functionality through the Command Palette with the command View: Split Editor.
Alternatively, you can use the associated keyboard shortcut:
- macOS: Cmd+\
- Windows or Linux: Ctrl+\
You can also open the split editor functionality by going to View → Editor Layout or by right-clicking on a file’s tab:

This setup is really useful when writing unit tests with your test code on the left and the module you’re testing on the right.
Some file types, like Markdown, have a preview region that you can use instead. Use the Markdown: Open Preview to the Side command to open the preview editor.
Using Zen Mode for Focused Work
If you need your absolute focus on a single file or task in VS Code, then use Zen Mode by going to View → Appearance → Zen Mode to show a full-screen window with just the editor:

This feature is especially useful for blocking out noisy distractions and notifications so that you can just focus on getting your current task done.
Theming
VS Code has a huge library of themes in the VS Code Marketplace. Some of the most popular themes out there are Material Theme, Winter is Coming, Dracula, Noctis, and Monokai Pro.
Let’s focus on the Material Theme as it comes with a broad set of color schemes to suit many tastes. You can install the extension from the Extensions view. Once installed, you can select a color theme by running Preferences: Color Theme in the Command Palette.
The Material Theme looks best with a custom icon theme. Icon themes are separate extensions from the color themes, so you have to install a second extension. Search for pkief.material-icon-theme in the Extensions view to find the most popular Material icon pack for the theme. After installing this, VS Code will prompt you to switch your icon pack.
This is the Material Theme with the Palenight color theme and the Material icon pack:

You can change the icon theme at any time from the Command Palette by using the command Preferences: File Icon Theme and then selecting one of the icon themes from the list.
Installing a Better Programming Font
Programming fonts are a special group of typefaces, typically with fixed-width characters called monospace. There’s a long list of available fonts to browse at ProgrammingFonts.org:

Once you’ve selected a font, go to Nerd Fonts to download it and install the font on your operating system. The downloads at Nerd Fonts are copies of the monospace fonts with support for glyphs, otherwise known as icons, which you can use inside the terminal prompt.
After installing your selected font, you need to change the editor.fontFamily setting to the name of the new font. You can do that by navigating to Code → Preferences → Settings and then selecting Text Editor → Font in the navigation dropdown. You can change the font your editor will use by adding the name of your new font in the first field of the Font Family setting.
Setting Up Your Terminal
You’ll spend much of your Python development time inside a shell terminal. You can use a separate application, like iTerm2 or Windows Terminal, but VS Code already has a powerful built-in terminal window.
Because VS Code does need a bit of configuration to make it as powerful as a dedicated terminal application, you’ll set that up now.
Changing the Default Shell Provider
You can reconfigure the terminal window to have multiple profiles. These profiles form the dropdown list when you spawn a new terminal.
VS Code allows you to configure multiple terminal profiles. You can’t edit terminal profiles in the settings UI, so you need to use the Preferences: Open Settings (JSON) command in the Command Palette to open the settings.json file. You’ll notice that key-value pairs make up the settings file. Each key represents the configuration setting for VS Code or one of its extensions.
There are three terminal profile settings, which have the following names:
| Operating System | Terminal Profile Settings |
|---|---|
| Windows | terminal.integrated.profiles.windows |
| Linux | terminal.integrated.profiles.linux |
| macOS | terminal.integrated.profiles.osx |
Once you type in the name, the editor autocompletes the default profiles into the JSON file.
Note that there’s no Python REPL profile in the default settings. You can add a profile with the key "python3-repl" to the integrated profiles JSON file so that VS Code makes it available as a profile option and drops you straight onto the REPL prompt:
"python3-repl": {
"path": "python3",
"args": ["-q"]
}
The -q flag is a Python command-line flag to stop the version header from showing. You can add any extra Python command-line flags to "args".
Once configured, your profiles should look something like this, depending on your OS:
"terminal.integrated.profiles.osx": {
"bash": {
"path": "bash",
"icon": "terminal-bash",
},
"zsh": {
"path": "zsh"
},
"pwsh": {
"path": "pwsh",
"icon": "terminal-powershell",
},
"python3-repl": {
"path": "python3",
"args": ["-q"]
}
},
VS Code has two launch modes for terminals: integrated and external. Once you’ve configured the profiles, you can set the default profile for your integrated terminal by setting the value for "terminal.integrated.defaultProfile.osx":
"terminal.integrated.defaultProfile.osx": "zsh",
If something gets launched in an external terminal, it will use the default shell of your operating system. If you prefer a different terminal app, like iTerm 2 for macOS or Windows Terminal for Windows, you can change the default external terminal as well:
"terminal.external.osxExec": "iTerm.app",
With this setting for macOS, for example, you’re saying that VS Code should bring up the iTerm app every time it launches an external terminal window.
There are even more settings you can change in regards to terminals in VS Code. For example, you can make VS Code activate your virtual environment automatically when you bring up a new terminal window, and you can customize the look and feel of your terminal by adding custom prompts. You’ll explore how to do both in this tutorial.
Virtual Environment Activation in the Terminal
Virtual environments are very important for managing multiple dependencies across Python projects. Visual Studio Code will activate any Python virtual environment once the interpreter is selected. If you already have a virtual environment, run Python: Select Interpreter from the Command Palette to select the Python interpreter virtual environment.
If you don’t have one, then create one inside the terminal. VS Code can automatically pick it up if the virtual environment path is named .venv/, env/, or venv/.
After you set the interpreter, you’ll automatically activate the virtual environment when you start a new terminal window inside VS Code:

If you already had a terminal open, you can destroy it by clicking the garbage can icon.
Any commands you run inside the terminal, such as python -m pip install, will be for the activated virtual environment.
In the above screenshot, you can see a custom command prompt that uses the Oh My Posh prompt toolkit. In the next section, you’ll install and configure Oh My Posh. Oh My Posh is optional, especially if you already have a custom command prompt installed.
Installing Oh My Posh
Oh My Posh is one of many libraries for customizing the command prompt of your terminal. It works across Linux, macOS, and Windows. It also works with all shells like Bash, Zsh, Fish, and PowerShell. You can install Oh My Posh to spice up your terminal.
If you’re on macOS and using Bash, run the following commands to install Oh My Posh:
$ brew tap jandedobbeleer/oh-my-posh
$ brew install oh-my-posh
$ curl https://github.com/JanDeDobbeleer/oh-my-posh/raw/main/themes/tonybaloney.omp.json -sLo ~/.mytheme.omp.json
$ echo "eval \"\$(oh-my-posh --init --shell bash --config ~/.mytheme.omp.json)\"" >> ~/.profile
$ . ~/.profile
If you’re on macOS and using Zsh, run the following commands to install Oh My Posh:
$ brew tap jandedobbeleer/oh-my-posh
$ brew install oh-my-posh
$ curl https://github.com/JanDeDobbeleer/oh-my-posh/raw/main/themes/tonybaloney.omp.json -sLo ~/.mytheme.omp.json
$ echo "eval \"\$(oh-my-posh --init --shell zsh --config ~/.mytheme.omp.json)\"" >> ~/.zprofile
$ . ~/.zprofile
If you’re on Windows and using PowerShell, run the following commands to install Oh My Posh:
PS C:\> Install-Module oh-my-posh -Scope CurrentUser
PS C:\> Add-Content $PROFILE "`nSet-PoshPrompt -Theme tonybaloney"
Finally, if you’re on Linux and using Bash, run the following commands to install Oh My Posh:
$ sudo wget https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/posh-linux-amd64 -O /usr/local/bin/oh-my-posh
$ sudo chmod +x /usr/local/bin/oh-my-posh
$ curl https://github.com/JanDeDobbeleer/oh-my-posh/raw/main/themes/tonybaloney.omp.json -sLo ~/.mytheme.omp.json
$ echo "eval \"\$(oh-my-posh --init --shell bash --config ~/.mytheme.omp.json)\"" >> ~/.bashrc
$ . ~/.bashrc
When you open up a new terminal in VS Code, you’ll get this prompt:

The components on the terminal are the folder, Git branch, and Python version. Check out the list of themes for some other options.
Note: If you’re using a custom terminal prompt like Oh My Posh or Oh My Zsh, you have to select one of the installed Nerd Fonts for the glyphs to render correctly in VS Code.
By default, the terminal will use the same font face that you configured for the editor, editor.fontFamily. You can override this by defining a different font family for the terminal.integrated.fontFamily identifier. You’ll also need to update any external terminal applications you use.
Team Settings vs Personal Settings
VS Code has two levels of settings:
- User settings, which apply to all projects
- Workspace settings, which only apply to that workspace
If a setting is declared in both, the workspace setting will override the user setting.
The workspace configuration for VS Code and all of its extensions live within a .vscode/ directory in the workspace root.
It’s a good idea to put your project-agnostic settings into your user settings and your project-specific settings into .vscode/. By separating your personal user settings from your project settings, you and any other developers working on the project can be more effective.
Global User Settings for Python
By default, the Python extension for Visual Studio Code has a very basic configuration. Many features like linting, formatting, and security checks are disabled because you need to install third-party tools like Black, Pylint, and Bandit to use them.
You can install these tools and make them available to every virtual environment by using either pipx or pip install --user. pipx is preferable over pip install --user because it’ll create and maintain a virtual environment for that package, keeping your global site packages smaller and reducing the risk of packaging conflicts.
Once you’ve installed pipx, you can install the common tools:
$ pipx install pylint && \
pipx install black && \
pipx install poetry && \
pipx install pipenv && \
pipx install bandit && \
pipx install mypy && \
pipx install flake8
Alternatively, use python3 -m pip install --user to install the common tools:
$ python3 -m pip install --user pylint black poetry pipenv bandit mypy flake8
Once you’ve installed the base tools, open the user settings from the Command Palette with Preferences: Open Settings (JSON). Add settings for the preferences you want to apply to all projects:
1"python.pipenvPath": "${env:HOME}/.local/bin/pipenv",
2"python.poetryPath": "${env:HOME}/.local/bin/poetry",
3"python.condaPath": "${env:HOME}/.local/bin/conda",
4"python.linting.enabled": true,
5"python.linting.banditPath": "${env:HOME}/.local/bin/bandit",
6"python.linting.banditEnabled": true,
7"python.linting.pylintPath": "${env:HOME}/.local/bin/pylint",
8"python.linting.mypyPath": "${env:HOME}/.local/bin/mypy",
9"python.linting.flake8Path": "${env:HOME}/.local/bin/flake8",
10"python.formatting.blackPath": "${env:HOME}/.local/bin/black",
With these settings, you’ve managed to accomplish a couple of things that’ll be useful for your development workflow across many projects:
- Lines 1 to 3 enable package discovery for projects enabled with
pipenv,poetry, andconda. - Line 4 enables Python linting.
- Lines 5 to 6 enable and set the path to
bandit. - Lines 7 to 10 enable Python formatting and set the path to a globally-installed instance of
pylint,mypy,flake8, andblack.
In each absolute path, you can automatically substitute your home folder by using the macro ${env:HOME}.
Workspace Settings
Outside of the user settings, you can use the .vscode/ directory inside the workspace to configure some project-specific settings:
- Which commands to run to execute the project
- How to test and debug the project
- Which linter and formatter to use and any project-specific parameters
The following files hold the VS Code preferences:
| File | Purpose |
|---|---|
settings.json |
VS Code settings |
launch.json |
Profiles to execute your project from the Run and Debug menu |
tasks.json |
Any additional tasks to execute, such as build steps |
Most of VS Code’s settings, as well as the settings for your extensions, are in these three files.
In the workspace preferences, the following predefined variables are supported:
| Predefined Variable | Meaning | |
|---|---|---|
${env.VARIABLE} |
Any environment variable | |
${workspaceFolder} |
The path of the folder opened in VS Code | |
${workspaceFolderBasename} |
The name of the folder opened in VS Code without any slashes (/) |
|
${file} |
The currently opened file | |
${fileWorkspaceFolder} |
The currently opened file’s workspace folder | |
${relativeFile} |
The currently opened file relative to workspaceFolder |
|
${cwd} |
The task runner’s current working directory on startup | |
${execPath} |
The path to the running VS Code executable | |
${pathSeparator} |
The character used by the operating system to separate components in file paths, for example, forward slash (/) or backslash (\) |
Using these variables will keep the project settings agnostic to the environment, so you can commit them into Git.
As an example of working with these settings, if you want to use Black as the default code formatter for this project, you can create the file .vscode/settings.json with this configuration:
{
"python.formatting.provider": "black",
}
Anyone who checks out this project will now automatically use Black as the formatter for Python files. You’ll see how this setting influences the autoformatting options in the section about setting format and lint on save.
Using the Settings Sync Extension
If you use VS Code across multiple computers, you can enable the automatic synchronization of Settings, Keyboard Shortcuts, User Snippets, Extensions, and UI State. If you haven’t used Settings Sync before, you’ll need to enable it:
- Run
Settings Sync: Turn Onin your Command Palette. - Follow the setup steps as prompted by VS Code. You can authenticate with GitHub.
- Once the setup is done, run
Settings Sync: Configurefrom the Command Palette. - Select what you want to sync.
Once Settings Sync is configured on all the computers you have VS Code installed on, you can see the state for each synced setting by running Settings Sync: Show Synced Data from the Command Palette, where they’ll show up under Synced Machines:

This view shows you the last synced time for each of the settings and which machines are in sync.
Linting and Formatting
All languages in Visual Studio Code can be formatted using one of the automated formatters, and the Python extension also supports linters. Linters and formatters perform different tasks:
- A formatter will change how your code looks but not how it works.
- A linter will warn you about your code’s compliance to standards on style, type adherence, security, and a range of best practices.
The Python extension supports many third-party linters, and they often perform different jobs. For example, Bandit is a linter for security bugs and Flake8 is a linter for style guide compliance.
The Python extension also comes with language server tooling, which performs analysis by loading the interfaces—methods, functions, classes—from your code and the libraries you use.
At the time of writing this tutorial, the latest and greatest language server extension for Python on Visual Studio Code is Pylance.
Setting Up Pylance
Pylance is an extension that works alongside Python in Visual Studio Code to provide deeper language support and introspection of Python code. Pylance will provide auto-completions, automated module imports, better code navigation, type checking, and tons more.
To get Pylance, go to the Extensions menu on the side bar and search Pylance (ms-python.vscode-pylance).
Note: Pylance is now bundled with the Python extension, so you might already have it installed.
Once you have Pylance installed, there are two default configuration settings you may want to change in your user settings to get the most out of the extension.
The first setting to change is the type checking mode, which you can use to specify the level of type checking analysis performed:
"python.analysis.typeCheckingMode": "basic"
By default, the type checking mode is set to "off".
The other options are "basic" or "strict". With "basic", rules unrelated to type checking and rules for basic type checking are run. If the mode is set to "strict", it will run all type checking rules at the highest severity of error. Set this to "basic" for a balance between strict and disabled.
The other default setting is python.analysis.diagnosticMode. By default, Pylance will inspect currently open files only. Changing this setting to workspace will inspect all Python files in the workspace, giving you a list of errors and warnings inside the Explorer view:

You should only set python.analysis.diagnosticMode to "workspace" if you have some RAM to spare as it will consume more resources.
Pylance is most effective when it has information about the types used as the arguments to methods and functions as well as the return types.
For external libraries, Pylance will use typeshed to infer the return types and argument types. Pylance also comes with type stubs and intelligence for some of the most popular data-science libraries, like pandas, Matplotlib, scikit-learn, and NumPy. If you’re working with pandas, Pylance will give you information and examples for common functions and patterns:

For libraries that don’t have type stubs on typeshed, Pylance will do its best to guess what the types are. Otherwise, you can add your own type stubs.
Setting Format and Lint on Save
Format Document is an action that applies formatting to any document in VS Code. For the Python extension, this action executes "python.formatting.provider", which can be set to any of the supported auto-formatters: "autopep8", "black", or "yapf".
Once you have configured the formatter in settings.json, you can set the formatter to run automatically whenever a file is saved. In the VS Code config, you can configure editor settings to only apply to certain file types by putting them in a "[<file_type>]" group:
...
"[python]": {
"editor.formatOnSave": true,
},
Along with the execution of the formatter, you can also have the import statements organized both alphabetically and by splitting standard library modules, external modules, and package imports into groups with the following configuration:
"[python]": {
...
"editor.codeActionsOnSave": {"source.organizeImports": true},
},
Unlike formatting, linting is specific to the Python extension. To enable linting, choose a linter by running Python: Select Linter on the Command Palette. You can also enable one or more linters in your settings. For example, to enable the Bandit and Pylint linters, edit your settings.json:
...
"python.linting.enabled": true,
"python.linting.banditEnabled": true,
"python.linting.pylintEnabled": true,
To run the enabled linters whenever a file is saved, add the following setting to settings.json:
...
"python.linting.lintOnSave": true,
You might find it helpful to have more than one linter enabled. Keep in mind that Pylance already provides many of the insights you would get from pylint, so you likely don’t need to enable both pylint and Pylance. In contrast, Flake8 provides stylistic feedback that Pylance doesn’t cover, so you can use those two together.
Testing Your Python Code in Visual Studio Code
Python offers plenty of tools to test your code. The Python extension for VS Code supports the most popular test frameworks, unittest and pytest.
Configuring Test Integration
To enable testing support for Python, run the Python: Configure Tests command from the Command Palette. VS Code will prompt you to select from one of the supported test frameworks and to specify which folder contains your tests.
This wizard adds the configuration options to .vscode/settings.json:
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": [
"tests"
],
You can edit python.testing.<framework>Args with your preferred test framework to add any additional command-line flags. The example above shows configuration options for pytest.
If you have more complex settings for pytest, put those in pytest.ini instead of the VS Code settings. That way, you’ll keep the configuration consistent with any automated testing or CI/CD tooling.
Executing Tests
Once you’ve configured the test framework and arguments for the test runner, you can execute your tests by running the Python: Run All Tests command from the Command Palette. This will start the test runner with the configured arguments and put the test output into the Python Test Log output panel:

Once test discovery has completed, each test case will have an inline option to execute or debug that case:

Failed tests will be marked as having an error. You can see the failure from the test runner in both the Python Test Log panel and by hover