This post contains some of my favorite tips and tricks for working with VSCode. For even more, I recommend VSCode’s own tips and tricks page.
I try to keep this post up-to-date, so the information should be compatible with recent versions of VSCode. For example, a lot of Python tools switched to extensions in 2022, and I have updated this page to reflect that.
Table of Contents
- Table of Contents
- Essential Shortcuts
- Customizing Your Editor
- Extensions
- Workspaces and Launch Configs
- Debugging & Testing
- Environment Variables & .env Files
- Connecting to Remote Instances
- Syncing Across Desktops
Essential Shortcuts
Action | Windows/Linux | Mac | Description |
---|---|---|---|
Command palette | Ctrl + Shift + P |
Cmd + Shift + P |
Access all VSCode commands |
Search by filename | Ctrl + P |
Cmd + P |
Quickly find and open files |
Autoformat | Alt + Shift + F |
Option + Shift + F |
Format your code according to language rules |
Clean up imports | Alt + Shift + O |
Option + Shift + O |
Organize and remove unused imports |
Run Jupyter cells | Shift + Enter |
Shift + Enter |
Execute code in Python interactive console |
Code completion | Control + Spacebar |
Control + Spacebar |
Manually trigger code suggestions |
Open terminal | No default hotkey | No default hotkey | Drag up from bottom of screen or use View menu |
Multi-line debugging | Hold Shift + Enter |
Hold Shift + Enter |
Enter multiple lines in debug console |
Customizing Your Editor
See my previous post for my recommended VSCode customizations and key bindings.
Settings
- You can use either the User Interface (
Preferences: Open Settings (UI)
) or edit the JSON directlyPreferences: Open Settings (JSON)
.
User settings are not stored in the project. Instead, they are at:
Platform | Location |
---|---|
Windows | C:\Users\<Username>\AppData\Roaming\Code\User\settings.json |
Mac | ~/Library/Application Support/Code/User/settings.json |
Common Python Settings
Setting | Purpose | Example |
---|---|---|
python.defaultInterpreterPath |
Set default Python interpreter | "/Users/julius/opt/anaconda3/envs/my_env/bin/python" |
python.testing.pytestArgs |
Configure pytest arguments | ["my_repo/path/to/tests"] |
pylint.interpreter |
Specify pylint’s Python interpreter | ["/Users/julius/opt/anaconda3/envs/all/bin/python"] |
Applying Settings to a Single Language
You can specify that you only want some settings to apply to a single language like so:
"[python]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": false,
"editor.tabSize": 4,
"editor.defaultFormatter": "ms-python.python"
},
Key bindings
Ctrl + k
to open key bindings. From there many things are just one button, such as z
for zen mode. Double tap “Esc” to escape.
If you just hit control + k
it brings up a list of key bindings, which you can customize.
Extensions
You can manage your extensions by clicking on the gear logo next to the extension.
This is where you can add specific details to your extensions.
You can also edit your .vscode/.settings
file to add the following:
"flake8.args": [
"--max-line-length=120"
]
Workspaces and Launch Configs
If you keep all your repos in a single folder like I do, I recommend putting your workspace file there (I call mine workspace.code-workspace
). That way all the folders and paths are straightforward. Sometimes it will by default put them in /Users/<username>/Library/Application Support/Code/Workspaces/<some_number>/workspace.json
. I don’t use them there.
Workspace File
You can include all your folders like this:
"folders": [
{
"path": "my_repo"
},
{
"path": "my_monorepo/python_package_a"
},
{
"path": "my_monorepo/python_package_b"
},
],
You can also optionally include "name"
if you want to change any of the names.
launch.json
Writing launch.json
files is very useful. It makes it easy to run files in different configurations, such as passing different arguments.
Common Configuration Options
Field | Description | Example |
---|---|---|
name |
Display name in the debug dropdown | "Python: Run New Config" |
type |
Debugger type (always “python” for Python) | "python" |
request |
Launch type (usually “launch”) | "launch" |
program |
Path to the file to run, absolute or relative | "${file}" or "/full/path/to/file.py" |
module |
Python module to run (alternative to program) | "my_module" |
console |
Where to display output | "integratedTerminal" , "internalConsole" , "externalTerminal" |
justMyCode |
Whether to only debug user code | true (default) or false |
args |
Command line arguments | ["--config", "my_config", "--num_gpus", "2"] |
env |
Environment variables | {"PYTORCH_ENABLE_MPS_FALLBACK": "1"} |
python |
Path to specific Python interpreter | "/home/julius/miniconda3/envs/my_env/bin/python" |
cwd |
Working directory | "${workspaceFolder}" or "${fileDirname}" |
subProcess |
Enable debugging of subprocesses | true |
Example Configurations
Here’s the default one for Python:
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
Here’s an example with arguments:
{
"name": "Python: Run New Config",
"type": "python",
"request": "launch",
"program": "/full/path/to/file.py",
"console": "internalConsole",
"justMyCode": false,
"args": [
"--config",
"my_config",
"--num_gpus",
"2",
]
},
Here’s how to run a Python module:
{
"name": "Python: My Module",
"type": "python",
"request": "launch",
"module": "my_module",
"justMyCode": true,
"args": ["my_arg"],
"env": {"PYTORCH_ENABLE_MPS_FALLBACK": "1"}
}
VSCode Variables
VSCode provides several useful variables that can be used in your configurations:
${file}
- The current opened file${workspaceFolder}
- The path of the workspace folder${fileDirname}
- The current opened file’s directory${fileBasename}
- The current opened file’s basename${fileExtname}
- The current opened file’s extension
Working Directory (cwd) Options
The cwd
field determines where your program starts executing from:
"cwd": "${workspaceFolder}"
- Start from the workspace folder- In a multi-folder workspace:
"${workspaceFolder:my_repo}"
- In a multi-folder workspace:
"cwd": "${fileDirname}"
- Start from the directory of the current file- Only recommended when running the current file (
"program": "${file}"
)
- Only recommended when running the current file (
- Note: When running a module, you typically don’t need to specify
cwd
Program vs Module
You can choose to run either a "module"
or a "program"
:
- Use
"program"
to run a specific file - Use
"module"
to run a Python module (uses Python’s-m
flag)
Debugging & Testing
Sometimes you have problems where Pylint seems to be using a different interpreter. Even if you select the correct interpreter and do it at the workspace level. I don’t know what causes this, but here is how to fix it:
It could be caused by having something in "pylint.interpreter": ["/Users/julius/opt/anaconda3/envs/all/bin/python"],
Discover Tests
Sometimes the Discover Tests functionality fails, often for path issues. Remember, even if it fails you can always runs tests by doing python -m pytest my_tests
if discover tests fails, go to the terminal - click on the output tab - and change it to Python Test Log
Failing Tests
If all your tests are failing because you’re getting an error seeing your app (ModuleNotFoundError: No module named 'my_app'
), here are some things you’ll want to consider.
You should open VS Code at the repo root. Even if you want to run just a selection of test cases, having it open at the repo root is best practice.
Then, update settings.json
and add something like this:
"python.testing.pytestArgs": [ "my_repo/path/to/tests" ]
This tells pytest
to only look in that folder, even though you’re working from the repo root.
Using Pytest and Unittest
If your tests use both unittest
and pytest
, you can make it work as long as you treat pytest
as the primary test runner. That’s because pytest
is compatible with unittest
. It can automatically discover and run test classes and methods written using the unittest
framework.
Other
If your linter can’t see it but you can run the file
maybe it’s a path that only works because of your .env file
Your linter doesn’t use that. So when you run it, it will run, but not for pytest or your linter… try to fix your linter by exporting the environment variables you want
The VSCode workspace setting python.pythonPath
is not to be confused with the environment variable $PYTHONPATH
.
python.pythonPath
is the path to the Python interpreter used for debugging or running the code, while $PYTHONPATH
is the environment variable which python uses to search for modules.
There are two different things going on here:
Where the computer looks for the python interpreter - python.pythonPath
And where that interpreter looks for packages - $PYTHONPATH
Environment Variables & .env Files
Sometimes environment variables won’t show up in VSCode. I’ve found that this can sometimes happen when VSCode is launched from the application icon. If this is happening, you can open VSCode directly from the terminal with code .
and it should have your environment variables. If you still don’t see them, make sure they are present in your terminal.
You can make .env
files to set environment variables. Go at top of directory. Can add environment variables, python path, etc.
Connecting to Remote Instances
I wrote a guide on how to connect to remote instances. I recommend storing your config file at ~/.ssh/config
Syncing Across Desktops
Here’s what I recommend keeping in sync between machines:
You can use either a work account or personal account. If you have Github Copilot in your work account, you’ll want to use that.