I’ve opened a project with the following structure in VS Code (1.71.0 on macOS, Intel) and activated a Dev Container (I’ve tried the default Python 3.9 and 3.10 containers from Microsoft, with and without using python3 -m venv ...
):
project/
.devcontainer/
devcontainer.json
Dockerfile
foo/
foo/
tests/
test_bar.py <-- IDE reports import error in this file
resources/
__init__.py
bar.py
setup.py
In VS Code’s terminal window, I can successfully run test_bar.py
from directory project/foo
with:
python3 -m unittest discover foo/tests -p 'test_*.py'
So the project is valid and runs OK from the command line.
But when I open file project/foo/foo/tests/test_bar.py
in VS Code, I see the error Unable to import 'foo' pylint(import-error)
underlined in red for the following line:
from foo import bar
I see similar supposed errors for external packages I’ve installed with pip3 install
.
I’ve tried to inform VS Code by adding various relative and absolute paths (e.g. /workspaces/project/foo
) to various places in project/.devcontainer.json
, such as at:
customizations.vscode.settings
python.analysis.extraPaths
python.autoComplete.extraPaths
python.testing.unittestargs
But I’ve had no luck so far (after many IDE restarts and container image rebuilds).
So I’m left wondering; how should one fix such IDE-flagged import errors in VS Code when using a Dev Container?
Additional Info
As a file was requested in the comments, here are the key test project files I used (I’ve not fixed any paths; my last test project was named vscode-python-dev-container
, not project
, which I used as shorthand above).
devcontainer.json
(with the containerEnv
section added for the suggested PYTHONPATH
change):
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/python-3
{
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3.10-bullseye",
// Options
"NODE_VERSION": "lts/*"
}
},
"containerEnv": {
"PYTHONPATH": "/workspaces/vscode-python-dev-container/foo"
},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
Dockerfile
:
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/python-3/.devcontainer/base.Dockerfile
# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster
ARG VARIANT="3.10-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
# COPY requirements.txt /tmp/pip-tmp/
# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt
# && rm -rf /tmp/pip-tmp
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
bar.py
:
"""An example module."""
JSON_STR = '{"a": 1}'
test_bar.py
:
"""An example test."""
import json
import unittest
import requests # test external lib access
from foo import bar
class TestFooBar(unittest.TestCase):
"""An example test class."""
a = requests.__name__ # to eliminate warning above that package isn't used
def test_foo_bar_json(self):
"""An example test."""
data = json.loads(bar.JSON_STR)
self.assertEqual(data['a'], 1)
2
Answers
I often have this same issue with Python+Devcontainer. What works for me is:
setting this env variable:
export PYTHONPATH=/workspace
, you can also try with/workspaces
or/yourProjectName
depending on your setup.restart the Python Language Server with
Ctrl+Shift+P
>Python: Restart Language Server
.Note that you do not need to rebuild the container. When you find the correct value for PYTHONPATH, you can add it to your Devcontainer configuration.
Is this issue completely resolved?
I believe it has to do something with your directory structure.
Please have a look at recommended directory structure here
If you don’t want to disturb your directory structure, you may consider below two entries:
devcontainer.json
file, givecontext:"."
Dockerfile
, adding appropriate entry forWORKDIR