如何正确设置 VisualStudio 代码的 PYTHONPATH

如何在 VisualStudio 代码中正确设置工作区的 $PYTHONPATH变量?

背景资料

我已经安装了两个版本的 GNURadio:

  1. /usr/lib/python2.7/dist-packages/gnuradio中的 Linux Mint 包管理器安装的 GNURadio 3.7.11版

  2. 由 PyBOMBS 在 /home/tejul/Documents/gr13/default/lib/python2.7/dist-packages/gnuradio中安装的 GNURadio 版本3.7.13.4(我的前缀目录是 ~/Documents/gr13/default)

只有在运行 setup_env.sh脚本(其中包括将 /home/tejul/Documents/gr13/default/lib/python2.7/dist-packages添加到 $PYTHONPATH)并在终端中启动 python 之后,才能使用 GNURadio 的新版本

tejul@Wacom:~/Documents/gr13/default$ ls
bin  etc  include  lib  libexec  setup_env.sh  share  src
tejul@Wacom:~/Documents/gr13/default$ source ./setup_env.sh
tejul@Wacom:~/Documents/gr13/default$ python
Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from gnuradio import gr
>>> gr.version()
'3.7.13.4'
>>>

不修改 $PYTHONPATH python ——自然地——导入旧版本的 GNURadio。

我想在 VisualStudio 代码中为新版本的 GNURadio 编写、运行和调试 python 脚本。我一直试图了解选择 Python 解释程序工作间环境的 VSCode。

据我所知,VSCode 工作区设置 abc0不能与环境变量的 abc1混淆。python.pythonPath是通往用于调试或运行代码的 Python 解释程序的路径,而 $PYTHONPATH是 python 通往 搜索模块的环境变量。

看起来 PyBOMBS 没有在我的前缀目录中安装自己的 python 解释器。因此,我需要在 /usr/bin/python2.7中的普通 python 解释器中使用 VSCode。因此,重新定义 VSCode 的 python.pythonPath或选择另一个 python 解释器对我没有帮助。

我需要让 VSCode 使用我自己版本的环境变量 $PYTHONPATH,它会告诉我的常规 python 解释器最好从 /home/tejul/Documents/gr13/default/lib/python2.7/dist-packages导入模块。

问题

文件之后,我在工作区目录中创建了自己的 .env文件,它设置 python 应该从哪些位置导入模块的优先顺序。唉,它对 python 解释器没有影响。

Showing that VSCode is ignoring my $PYTHONPATH setting

你能看出我做错了什么吗? 我也试过:

  • 将 PYTHONPATH 设置为一个更高的文件夹级别,即 /home/tejul/Documents/gr13/default/lib/python2.7,这没有帮助
  • 调用变量 $PYTHONPATH而不是 PYTHONPATH,这没有帮助
  • 在每次更改 .env文件后重新启动 VSCode,这没有帮助
  • 在路径字符串周围使用双引号,例如 PYTHONPATH="/home/tejul/Documents/gr13/default/lib/python2.7:/usr/lib/python2.7",这没有帮助
160229 次浏览

Setting PYTHONPATH in .env works for me. Note that the effect just is for vscode and the tools it runs, such as pylint.

My situation: I have a project that is not a pip installable package, but simply a source folder. (For historical reasons...)

myproject/src

The project has dependencies defined in a pip requires file.

My setup:

  1. I create a virtualenv, and install the packages from the requires file.
  2. I open vscode in the folder myproject - so this becomes the root of the vscode "project".
  3. I point vscode to use the virtualenv as the python interpreter. This will make imports of dependencies installed with pip work. (For linters, intellisense, etc)
  4. To also make imports from my project source work for the linters (pylint especially) in vscode, I add a .env with this content, adding my project source folder to the PYTHONPATH:
PYTHONPATH=./src:${PYTHONPATH}

OP seemed to have asked about path syntax for the .env file and the vscode set up so that it finds and reads some custom module files. My problem was similar in that I wanted code to find my custom modules for import in a script. I did not want to put my custom modules in a folder inside my python environment. I also wanted to avoid setting one or more paths as PYTHONPATH for the User Variables in the Windows Environment Variables - but this will work if you want to do it. I am working in vscode in Windows 10.

1) SYNTAX:

a) I found that the following path syntax works in the env file:

PYTHONPATH = C:/0APPS/PYTHON/_MODULES

My .py module files are in this folder.

b) # works for comments in the .env file.

2) VSCODE SET-UP: I found that the following works:

a) Like sunew said at #2 My setup: Use the Explorer in vscode to open at your selected project workspace folder. For me that is Q:\420 PYTHON

b) Give the env file a name, like vscode.env file and place it in that folder at the top level of the workspace.

c) Open vscode settings and search .env where under the Extensions > Python you will find "Python: env file". Edit the box to add your env file name just before .env. e.g. ${workspaceFolder}/vscode.env

d) import custom_modulename now work for me - in the python interactive window and in a script.

This question deserves an upvote because the documentation is missing some important details.

Example

Suppose your project layout is like this

myproject/
.vscode/
settings.json
.env
src/
a_module.py
tests/
test_a.py

Open the settings.json fie and insert these lines

"terminal.integrated.env.windows": {
"PYTHONPATH": "${workspaceFolder}/src;${workspaceFolder}/tests"
},
"python.envFile": "${workspaceFolder}/.env",

Note that ${workspaceFolder} evaluates to myproject, it is not to the .vscode folder.

In the .env file enter this

WORKSPACE_FOLDER=C:/full/path/to/myproject
PYTHONPATH=${WORKSPACE_FOLDER}/src;${WORKSPACE_FOLDER}/tests

Note that on Windows the slashes in the path lean forward, like so /. Different paths are separated with a ; (on other platforms with a :).

This blog was helpful.

I have a situation that I believe is relatively common. I want a script to import a module from another directory. My python project is laid out as follows:

~/project/
|
|---modules/
|
|---mod.py
|---scripts/
|---script.py

in script.py, I have from modules import mod. So my PYTHONPATH needs to be set to ~/project/ (something that PyCharm does automatically).

VSCode is a great editor, but everywhere else, it falls short, in my opinion. This is a perfect example of that.

I create a default launch.json file to "run the current file". A "cwd": "${fileDirname}" line has to be added to make things work like they do in PyCharm (FYI, a list of the built-in variables can be found here).

Debugging

For debugging (the "play" button on the sidebar, or the F5 key), the PYTHONPATH set in launch.json or your .env file takes effect. Note that in the .env file, you cannot use variables such as ${workspaceRoot}, but you can easily append or insert to the path by using the proper separator for your platform (; for Windows and : for everyone else).

Because I want to take advantage of that variable, I put this in my launch.json:

    "env": {"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}

(Thanks to @someonr for the suggestion to use ${pathSeparator}.)

It appears that you can prepend/append to whatever is inherited from the environment (this is not true for settings.json; see below).

This will also work for the hotkey Ctrl+F5 (run without debugging).

For reference, here's the full file, which replicates what PyCharm does automatically:

{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"cwd": "${fileDirname}",
"env": {"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
}
]
}

Run in terminal

If I hit the "play" button that appears on the top right of the editor window (when a python file is the active tab), it will not work. This runs the current file in a terminal, which doesn't pay attention to launch.json at all. To make that work, you have to define PYTHONPATH in a settings.json file, by adding this:

    "terminal.integrated.env.osx": {"PYTHONPATH": "${workspaceFolder}"}

(Note there are different values for each platform.) If you've selected a python interpreter (e.g. from a virtual environment), you will already have a settings.json file in the .vscode directory. Mine looks like this:

{
"python.pythonPath": "/Users/me/project/venv/bin/python3",
"terminal.integrated.env.osx": {"PYTHONPATH": "${workspaceFolder}"}
}

You can't append or insert values into the inherited PYTHONPATH via the settings.json file. It will only take one string, and it will not parse separators. So even though you could get the value using ${env:PYTHONPATH}, you won't be able to do anything with it.

Moreover, you can't set the current working directory. Even though it would seem you could set it with "terminal.integrated.cwd": "${workspaceFolder}", it doesn't work. So if any of your scripts do anything with paths relative to their location in the tree, they won't work. The working directory will be your project root.

Note that any changes to the settings.json file will require that you exit the integrated terminal and restart it.

Linting

Nothing I do to launch.json regarding PYTHONPATH makes any difference to pylint, which will red-underline from modules import mod, despite the fact I can put the cursor on mod, hit F12, and the file opens. Snooping around linting settings, the defaults for mypy include --ignore-missing-imports. To replicate this behavior with pylint, add this to your settings.json:

    "python.linting.pylintArgs": [
"--disable=F0401"
]

Shame that we just have to work around this, but the autocomplete helps a lot when writing the import statements to begin with.

Conclusion

There are many layers to VSCode and it's hard to get things to work together. It seems multiple environments are floating around. In the end:

  1. I cannot "run in terminal" because I can't set the current working directory to be the path containing the current file.
  2. I cannot set PYTHONPATH for pylint as that runs in some environment different than the integrated terminal and whatever is controlled by launch.json, so I can only tell pylint to ignore import errors.
  3. Running with F5 works if you set PYTHONPATH either via an .env file or in launch.json

Linux user here. I had trouble getting it to work and there is a lot of interaction with other vscode Python extension settings, but the following worked for me:

  • Close all workspaces.

  • Add a single folder that you wish to be the root folder of your new workspace.

  • Put your .env file there containing PYTHONPATH=/path/to/a:/path/to/b on a single line by itself. Do not use double quotes around the value.

  • Restart vscode

  • Create a test.py script that imports a package or module within your folder

  • vscode should allow your import statement, and should autocomplete to code within your folder.

Two other issues that I spent a long time figuring out (despite the great answers above) which may help others:

  1. Make sure that you have configured VS Code to allow terminal configurations to amend your shell settings (via Manage Workspace Shell Permissions (see https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration). Otherwise VS Code silently ignores your terminal.integrated.env.{platform} settings.
  2. Pylint will only search for other modules in the worspace directory if the module from which it is launched is in a folder which is a package (ie has _init_.py file) (See https://docs.pylint.org/en/1.6.0/run.html) meaning that pylint will continue to highlight import errors despite the code running properly due to the VS Code launch.json configured as above.

For tools like Pyright you can edit python.analysis.extraPaths in the workspace settings.json.

Example:

{
...
"python.analysis.extraPaths": [
"src/apps",
"src/override_apps"
],
...
// next lines can be different
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.linting.mypyEnabled": false,
"python.pythonPath": "environment/bin/python",
...
}

Edit settings.json in your vs code workspace folder

{
"python.pythonPath": "*python package path*",
"terminal.integrated.env.windows": {
"PYTHONPATH": "${workspaceFolder}/*sub folder*;*python package path*"
},
"python.defaultInterpreterPath": "*path to python exe*",
"python.analysis.extraPaths": [
"*python package path*",
"*python package path*"
],
"python.autoComplete.extraPaths": [
"*python package path*",
"*python package path*"
]}

Works good!

I also had a similar issue where I was using the vs-code on a remote server over ssh, the server had multiple user-accounts so the typical ubuntu python path did not work for me.

The easiest way, I have found for doing debugging was to first find out my own python install location using "which python". The output would be something like "/home/user_name/anaconda3/bin/python".

Then in vs-code, I manually set the python interpreter location to be the above location. I did this by clicking on the python tab on the bottom of vs code. like the Python 3.8.5 64-bit in this picture. This will open the command pallete asking for the location of python interpreter, as shown in this image. manually put the location of python install here. After doing all these steps, my python debugging is working smoothly.

Running VSCode 1.6.2, with Python extension v2021.10.1365161279 on Windows 10.

Debugging works based on the env file, I used the default file .env:
PYTHONPATH=<full_path_to_the_workspace_folder>

Running works based on the .vscode/settings.json file with such a setting
"terminal.integrated.env.windows": {"PYTHONPATH": "<full_path_to_the_workspace_folder>"}
just that I found I needed to disable+reload+enable the extension if I changed the path.

Using VS Code, a pip virtual env, you can put at the end of the .venv/bin/activate file:

export PYTHONPATH="${PYTHONPATH}:/path/to/your/package"

package -> module1 -> abc.py and you can use: import module.abc etc.

These are 3 different ways to solve the issue :

1/ Editing PYTHONPATH :

  • export PYTHONPATH=/Users/.../Projects/MyNewProject/src
  • python3 myfile.py to run the file

2/ Editing VSCode settings :

  • add "terminal.integrated.env.osx": {"PYTHONPATH": "${workspaceFolder}/src"} to settings.json in VScode

3/ Adding a setup.py file to your src/ directory.

  • create the file src/setup.py
from setuptools import find_packages, setup


setup(
name="sample",
description="Sample Python Project",
packages=find_packages(),
)
  • run python -m pip install -e ./src/ to install all modules in src/ as packages

After for reasons unknown my .venv/Lib/site-packages/.pth solution failed, as well as my subsequent .vscode\settings.json one, and an .env didn't work on my Windows 10*, I settled for the environment-independent way to import ./src/lib.py in ./test/test_lib.py:

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), '../src'))
from lib import foo

That also works in non-IDE terminals, and VS Code's pycodestyle still complains when I forget an extra newline between functions.

*: VS Code 1.70.0 release note:

Loading environment variables from .env files

A number of fixes have been made to loading environment variables from .env files, including detecting changes to the .env files. Python kernels will now load environment variables from the file defined in the setting python.envFile.