Visual Studio Code working with Python with PYTHONPATH and separate source and tests folders

75 Views Asked by At

Given a project structure:

* project
  * src
    * my_package
      * __init__.py
      * code_file.py
  * tests
    * __init__.py
    * my_package
      * __init__.py
      * code_file_test.py

How do I get Visual Studio code to identify that src is the root for code files so this will work for all of these:

  1. intellisense

  2. running

  3. discovering and running tests

1

There are 1 best solutions below

4
Danny Varod On

In IntelliJ so can right click the src folder and mark it as the source root. There is no simple solution in VSC, however, this workaround could help.

Under the project root add the following file:

.vscode/settings.json

* project
  * .vscode
    * settings.json

with the following content:

{
    "python.analysis.extraPaths": ["${workspaceFolder}/src/", "${workspaceFolder}/"],
    "python.autoComplete.extraPaths": ["${workspaceFolder}/src/", "${workspaceFolder}/"],
    "terminal.integrated.env.windows": {
        "PYTHONPATH": "${workspaceFolder}\\src;${workspaceFolder}"
    },
    "terminal.integrated.env.linux": {
        "PYTHONPATH": "${workspaceFolder}/src:${workspaceFolder}"
    },
    "python.testing.unittestArgs": [
        "-v",
        "-t", ".",
        "-s", "./tests",
        "-p", "*test.py"
    ],
    "pythonTestExplorer.testFramework": "unittest",
    "python.testing.pytestEnabled": false,
    "python.testing.unittestEnabled": true
}

(The two last parameters assume you are using the unittest python framework, change if using another one.)

If this doesn't work, make sure you have the following extensions installed:

ms-python.python
ms-python.vscode-pylance
ms-vscode.test-adapter-converter
hbenl.vscode-test-explorer
littlefoxteam.vscode-python-test-adapter

If the above doesn't work, try restarting VSC, if that doesn't work, you may have to alter imports like this...

In src code:

# Instead of: from my_package.different_file import AnotherClass
# use:
from .different_file import AnotherClass

# Instead of: from my_other_package.different_file import AnotherClass
# use:
from ..my_other_package.different_file import AnotherClass

In tests code:

try:
    from my_package.my_file1 import MyClass1
    from my_package.my_file2 import MyClass2
except ImportError:
    from src.my_package.my_file1 import MyClass1
    from src.my_package.my_file2 import MyClass2
    pass