Environment $PATH different when using venv - python

I'm using PyCharm on a mac (OSX mavericks) to run a simple script shown below. All it does is print the PATH variable. I have a virtualenv in the project directory. I added a Run Configuration in PyCharm and tried it with different Pythons:
# file mytest.py
import os
print "PATH: ", os.environ['PATH']
When I run with the system default python (/usr/bin/python) it prints the correct value for PATH (i.e. the PATH as I have configured in my .bash_profile file,) which is kind of long and contains many directories.
But when I choose the venv's Python, the path is reduced to only: /usr/bin:/bin:/usr/sbin:/sbin:/Users/myname/projects/myproj/venv/bin
This doesn't happen if I run the script from a terminal window. In this case it shows the correct PATH for both the system's python and the venv python. It also doesn't happen if I deactivate the venv and run venv/bin/python mytest.py.
Anyone knows how to make the correct PATH value be set when running from PyCharm and using venv?

you should probably know that all environment variables are inherited.
When you define environment variable in your .bash_profile it becomes available in your terminal (bash),
and in all processes that will be started from terminal (These processes will be children for the bash process).
That's why you are getting expected values when running your script from within the terminal.
You start PyCharm not from a terminal, so it doesn't inherit PATH. And so do Python or venv (they launched from PyCharm).
To solve your issue you have 3 options here: just start PyCharm from terminal or move PATH variable definition from .bash_profile to session init scripts (PATH will be defined system-wide) or Duplicate your PATH in PyCharm's run configuration (it has such option over there)
Good luck!

I built something for SublimeLint that figures out your shell's PATH in Python.
https://github.com/lunixbochs/sublimelint/blob/st3/lint/util.py#L57
Basically, it runs $SHELL --login, echoes your path, and parses it.
The gist is:
import os
import subprocess
shell = os.path.basename(os.environ['SHELL'])
output = subprocess.Popen(
(shell, '--login', '-c', 'echo __SEP__$PATH'),
stdout=subprocess.PIPE).communicate()[0] or ''
print output.split('__SEP__', 1)[1].split(':')

The problem for me on windows was case related: it's the difference between Path and PATH.
If you choose:
Edit configurations
Environment Variables
Show (down in the bottom right corner)
This shows the environment variables. On my system there is no PATH, only Path.
Defining a new PATH environment variable wouldn't work, but Path worked fine.

There's a workaround in my case.
To modify the environment variable PATH, I usually just need to add extra paths to the PYTHONPATH variable in the run configuration's environment variables setting.
PYTHONPATH will then be added to PATH.

Related

Auto activate virtual environment in Visual Studio Code

I want VS Code to turn venv on run, but I can't find how to do that.
I already tried to add to settings.json this line:
"terminal.integrated.shellArgs.windows": ["source${workspaceFolder}\env\Scripts\activate"]
But, it throws me an 127 error code. I found what 127 code means. It means, Not found. But how it can be not found, if I see my venv folder in my eyes right now?
I think it's terminal fault. I'm using Win 10 with Git Bash terminal, that comes when you install Git to your machine.
This is how I did it in 2021:
Enter Ctrl+Shift+P in your vs code.
Locate your Virtual Environment:
Python: select interpreter > Enter interpreter path > Find
Once you locate your virtual env select your python version:
your-virtual-env > bin > python3.
Now in your project you will see .vscode directory created open settings.json inside of it and add:
"python.terminal.activateEnvironment": true
don't forget to add comma before to separate it with already present key value pair.
Now restart the terminal.
You should see your virtual environment activated automatically.
Actually the earlier suggested solutions didn't work for me, instead I added the following in my settings:
"settings": {
"python.terminal.activateEnvInCurrentTerminal": true,
"python.defaultInterpreterPath": "~/venv/bin/python"
}
Of course replace the defaultInterpreterPath (used to be pythonPath) setting with your own path (so don't copy/paste the second line).
You don't need this line at all. Just remove it and switch your Python interpreter to point to the one within your venv. Here's a relevant documentation (italicized emphasis mine):
To select a specific environment, use the Python: Select Interpreter
command from the Command Palette (Ctrl+Shift+P).
... and
opening a terminal with the Terminal: Create New Integrated Terminal
command. In the latter case, VS Code automatically activated the
selected environment.
Once you switch the interpreter VS code should create a .vscode folder within your workspace with a settings.json indicating the python interpreter. This will give VS code the direction of where to locate the venv.
There is a new flag that one can use: "python.terminal.activateEnvironment": true
my scenario was pretty much the same. I am running VSCode on Windows, wanting to used git bash as my default Terminal but after the venv got created, it was doing some weird stuff when a Terminal would open where it couldn't find the correct python interpeter in the venv/Scripts folder even though I did ctrl-shift-p a bunch of times to reset it to the python.exe there. I also wanted to make sure the activate script was run on Terminal open. I just couldn't get the debugger to work right and it kept complaining that it could not find the python interpreter, so I basically couldn't debug at all.
So for anyone who is having weird stuff happen trying to use a Git Bash Terminal in VSCode in Windows related to a python project using a virtual env, here is what I found out;
I noticed that when I opened a new Git Bash Terminal, and looked at the $PATH variable to make sure it could find the interpreter in the venv, the path to the venv/Scripts folder would be prepended to the $PATH, but not with linux path separators like everything else in $PATH but with a Windows style path;
echo $PATH
C:\Users\blah\Documents\blah\Stock-down\Dev\this_api\venv/Scripts:/c/Users/blah/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/blah/bin:/c/Program Files/Go/bin:/c/Python39/Scripts:
So whenever I would try to debug, or just even run which python, It would get confused and thought the interpreter was in here;
which python
C:\Users\blah\Documents\blah\Stock-down\Dev\this_api\venv/Scripts/C/Users/blah/Documents/blah/Stock-down/Dev/this_api/venv/Scripts/python.exe
I ran the "printenv" command in the Terminal to see what env vars were getting set and why the venv interpreter path was getting messed up. And I found a env var I didn't know existed - VIRTUAL_ENV. But I didn't know how it was getting set or where it came from. After some pain, and hunting around I found it - when you run "python -m venv venvname" to create the virtual env in the project folder, as you know, it creates the activate (and activate.bat for windows) scripts in the ./venv/Scripts folder. Inside these files this VIRTUAL_ENV variable is not only exported, but but prepended to the $PATH variable on Terminal open with the "/Scripts" folder name added in linux path style. The problem with is that it sets the VIRTUAL_ENV value with windows type path - I know its painful and wrong to do this, but I just changed it to what Git Bash is expecting, see below;
#unset irrelevant variables
deactivate nondestructive
#VIRTUAL_ENV="C:\Users\blah\Documents\blah\Stock-down\Dev\this_api\venv"
VIRTUAL_ENV="/c/Users/blah/Documents/blah/Stock-down/Dev/st_api/venv"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/Scripts:$PATH"
export PATH
Now when a new Git Bash Terminal is opened it prepends the venv/Scripts path correctly to $PATH;
echo $PATH
/c/Users/blah/Documents/blah/Stock-down/Dev/st_api/venv/Scripts:/c/Users/blah/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/blah/bin:/c/Program Files/Go/bin:/c/Python39/Scripts:
I also made a copy of the executable python.exe in the ./venv/Scripts dir and just called it "python" and now the command "which python" works and I can debug fine. I still set ctrl-shift-P when I choose the interpreter in VSCODE to "python.exe" when I just use "find" during the selection.
For more information on VIRTUAL_ENV var, see this doc -- python venv docs
It feels like jumping through a bunch of hoops I know, but this way I can open a new Git Bash Terminal, have the activate script run correctly on Terminal Open, debug, and operate normally without having to float between Git Bash AND WSL Ubuntu AND Powershell, etc.
My environment started to activate automatically after the advice from this article
When you create a new virtual environment, a prompt will be displayed
to allow you to select it for the workspace. This will add the path to
the Python interpreter from the new virtual environment to your
workspace settings. That environment will then be used when installing
packages and running code through the Python extension. For examples
of using virtual environment in projects, see the Python, Django, and
Flash tutorials.
My solution was to create /.vscode/settings.json manually
Here is the tree;
├───django
│ ├───.vscode
│ │ ├───settings.json
I created /.vscode/settings.json then added this code in settings.json (I am using windows so I used double backslash for path location otherwise it gives unicode error, and don't copy paste this, find your own .virtualenvs)
{
"python.defaultInterpreterPath": "C:\\Users\\Talha\\.virtualenvs\\django-okd21pq9\\Scripts\\python.exe"
}

Windows 10 Bash and python paths

I've recently installed the windows bash. I tryed to make the packages installed with Anaconda visible by adding them to the PYTHONPATH variable but it is not listed in the environment.
Couriously enough sys.path.append works just fine and has entries, as sys.path doc states that the package variable is instatiated from the environment variable PYTHONPATH, but how can it be if it is not present in the environment (Bash of windows)?
I've already checked the windows environment and they're as separated system (otherwise the Anaconda packages would be available for import). So where can I set the python paths to new modules in windows bash?
If you are launching python from windows bash it won't automatically find your PYTHONPATH environment variable from windows. You need to add it yourself. You can do this by editing the .bashrc file. It is located in your home directory (/home/userid or just ~).
vi ~/.bashrc
Now add the following line:
export PYTHONPATH="/mnt/c/my/python/path"
If you are using some IDE like PyCharm, it may create it's own PYTHONPATH. It certainly won't be visible from system.
You may create PYTHONPATH variable on your own from system settings (Control Panel etc). But if something like IDE then replace it locally, your modules won't be able to import.
The stable but a bit rude way is modify the windows registry by modifying a value in PYTHONPATH record.
The code that uses RapidEE utility (RAPIDEE_EXECUTABLE is path to your rapidee.exe) to achieve that
def set_pythonpath():
subprocess.call([RAPIDEE_EXECUTABLE, '-S', '-C', 'PYTHONPATH', YOUR_PACKAGE_PATH])

os.system does not look the programs that are in my path

I have a problem when calling programs inside a python script. The programs that are giving me problems are those that I have installed manually on my computer and then added them to path on .bashrc file. The programs that where installed using 'sudo apt-get install some_program' don't give me any problem
The programs where added to my .bashrc file as the following way:
#path to fastqc
export PATH=$PATH:/home/bioinfor3/bin/FastQC/
#path to fastx-toolkits
export PATH=$PATH:/home/bioinfor3/bin/fastx/
Inside my PyCharm, I am using the os module to call those programs the in the below manner:
os.system('fastqc seq.fastq')
And I get this error
sh: 1: fastqc: not found
I guess it has something to do with the sh path or something, but I am not able to make it work
EDIT:
If Pycharm is launched from the terminal, it inherits the bashrc file with my personal paths and it works
Presumably this is happening because you have modified your login environment to adjust your PATH, but this updated path isn't seen by the shell that's running PyCharm, or PyCharm appears to be nullifying it somehow.
You should first of all verify that
os.system('/home/bioinfor3/bin/FastQC/fastqc seq.fastq')
operates as you would expect (no reason why it shouldn't, but worth checking).
It seems from this answer that by default PyCharm doesn't use bash for its shell but tcsh. Therefore it isn't seeing the setting you are enforcing on bash.

When I use Pycharm run a python file(in fact it is my first use), always report error, for example: [duplicate]

I need to debug an py-script in PyCharm that makes use of unix binaries like "which, grep" and so on.
If I start the py-script from Terminal (bash), unix binaries are found and all works like expected.
If I start the script from PyCharm "Debug" or "Run", there seems to be no "PATH" set => the unix binaries were not found.
Am I missing sth.?
Add the PATH environment variable to your Run Configuration (Run->Edit Configurations…) like this: /usr/local/bin:$PATH
Create a new environment variable in your run configuration named PATH, and set it equal to the output of running echo $PATH on your command line. This will let you get around the issue.
I have had to manually symlink binaries that are in your PATH, but not in /usr/bin/. For example, scripts running 'ffmpeg' in pycharm will not see /usr/local/bin/ffmpeg but after symlinking will be able to see /use/bin/ffmpeg. This is a python subprocess issue (they don't consult your .bashrc as bash does).

Python 3, sys.path doesn't work, how to permenantly append a path? [duplicate]

Whenever I use sys.path.append, the new directory will be added. However, once I close python, the list will revert to the previous (default?) values. How do I permanently add a directory to PYTHONPATH?
If you're using bash (on a Mac or GNU/Linux distro), add this to your ~/.bashrc
export PYTHONPATH="${PYTHONPATH}:/my/other/path"
You need to add your new directory to the environment variable PYTHONPATH, separated by a colon from previous contents thereof. In any form of Unix, you can do that in a startup script appropriate to whatever shell you're using (.profile or whatever, depending on your favorite shell) with a command which, again, depends on the shell in question; in Windows, you can do it through the system GUI for the purpose.
superuser.com may be a better place to ask further, i.e. for more details if you need specifics about how to enrich an environment variable in your chosen platform and shell, since it's not really a programming question per se.
Instead of manipulating PYTHONPATH you can also create a path configuration file. First find out in which directory Python searches for this information:
python -m site --user-site
For some reason this doesn't seem to work in Python 2.7. There you can use:
python -c 'import site; site._script()' --user-site
Then create a .pth file in that directory containing the path you want to add (create the directory if it doesn't exist).
For example:
# find directory
SITEDIR=$(python -m site --user-site)
# create if it doesn't exist
mkdir -p "$SITEDIR"
# create new .pth file with our path
echo "$HOME/foo/bar" > "$SITEDIR/somelib.pth"
This works on Windows
On Windows, with Python 2.7 go to the Python setup folder.
Open Lib/site-packages.
Add an example.pth empty file to this folder.
Add the required path to the file, one per each line.
Then you'll be able to see all modules within those paths from your scripts.
In case anyone is still confused - if you are on a Mac, do the following:
Open up Terminal
Type open .bash_profile
In the text file that pops up, add this line at the end:
export PYTHONPATH=$PYTHONPATH:foo/bar
Save the file, restart the Terminal, and you're done
You could add the path via your pythonrc file, which defaults to ~/.pythonrc on linux. ie.
import sys
sys.path.append('/path/to/dir')
You could also set the PYTHONPATH environment variable, in a global rc file, such ~/.profile on mac or linux, or via Control Panel -> System -> Advanced tab -> Environment Variables on windows.
To give a bit more explanation, Python will automatically construct its search paths (as mentioned above and here) using the site.py script (typically located in sys.prefix + lib/python<version>/site-packages as well as lib/site-python). One can obtain the value of sys.prefix:
python -c 'import sys; print(sys.prefix)'
The site.py script then adds a number of directories, dependent upon the platform, such as /usr/{lib,share}/python<version>/dist-packages, /usr/local/lib/python<version>/dist-packages to the search path and also searches these paths for <package>.pth config files which contain specific additional search paths. For example easy-install maintains its collection of installed packages which are added to a system specific file e.g on Ubuntu it's /usr/local/lib/python2.7/dist-packages/easy-install.pth. On a typical system there are a bunch of these .pth files around which can explain some unexpected paths in sys.path:
python -c 'import sys; print(sys.path)'
So one can create a .pth file and put in any of these directories (including the sitedir as mentioned above). This seems to be the way most packages get added to the sys.path as opposed to using the PYTHONPATH.
Note: On OSX there's a special additional search path added by site.py for 'framework builds' (but seems to work for normal command line use of python): /Library/Python/<version>/site-packages (e.g. for Python2.7: /Library/Python/2.7/site-packages/) which is where 3rd party packages are supposed to be installed (see the README in that dir). So one can add a path configuration file in there containing additional search paths e.g. create a file called /Library/Python/2.7/site-packages/pip-usr-local.pth which contains /usr/local/lib/python2.7/site-packages/ and then the system python will add that search path.
On MacOS, Instead of giving path to a specific library. Giving full path to the root project folder in
~/.bash_profile
made my day, for example:
export PYTHONPATH="${PYTHONPATH}:/Users/<myuser>/project_root_folder_path"
after this do:
source ~/.bash_profile
On linux you can create a symbolic link from your package to a directory of the PYTHONPATH without having to deal with the environment variables. Something like:
ln -s /your/path /usr/lib/pymodules/python2.7/
For me it worked when I changed the .bash_profile file. Just changing .bashrc file worked only till I restarted the shell.
For python 2.7 it should look like:
export PYTHONPATH="$PYTHONPATH:/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python"
at the end of the .bash_profile file.
Adding export PYTHONPATH="${PYTHONPATH}:/my/other/path" to the ~/.bashrc might not work if PYTHONPATH does not currently exist (because of the :).
export PYTHONPATH="/my/other/path1"
export PYTHONPATH="${PYTHONPATH}:/my/other/path2"
Adding the above to my ~/.bashrc did the trick for me on Ubuntu 16.04
This is an update to this thread which has some old answers.
For those using MAC-OS Catalina or some newer (>= 10.15), it was introduced a new Terminal named zsh (a substitute to the old bash).
I had some problems with the answers above due to this change, and I somewhat did a workaround by creating the file ~/.zshrc and pasting the file directory to the $PATH and $PYTHONPATH
So, first I did:
nano ~/.zshrc
When the editor opened I pasted the following content:
export PATH="${PATH}:/Users/caio.hc.oliveira/Library/Python/3.7/bin"
export PYTHONPATH="${PYTHONPATH}:/Users/caio.hc.oliveira/Library/Python/3.7/bin"
saved it, and restarted the terminal.
IMPORTANT: The path above is set to my computer's path, you would have to adapt it to your python.
The script below works on all platforms as it's pure Python. It makes use of the pathlib Path, documented here https://docs.python.org/3/library/pathlib.html, to make it work cross-platform. You run it once, restart the kernel and that's it. Inspired by https://medium.com/#arnaud.bertrand/modifying-python-s-search-path-with-pth-files-2a41a4143574. In order to run it it requires administrator privileges since you modify some system files.
from pathlib import Path
to_add=Path(path_of_directory_to_add)
from sys import path
if str(to_add) not in path:
minLen=999999
for index,directory in enumerate(path):
if 'site-packages' in directory and len(directory)<=minLen:
minLen=len(directory)
stpi=index
pathSitePckgs=Path(path[stpi])
with open(str(pathSitePckgs/'current_machine_paths.pth'),'w') as pth_file:
pth_file.write(str(to_add))
Just to add on awesomo's answer, you can also add that line into your ~/.bash_profile or ~/.profile
The add a new path to PYTHONPATH is doing in manually by:
adding the path to your ~/.bashrc profile, in terminal by:
vim ~/.bashrc
paste the following to your profile
export PYTHONPATH="${PYTHONPATH}:/User/johndoe/pythonModule"
then, make sure to source your bashrc profile when ever you run your code in terminal:
source ~/.bashrc
Hope this helps.
I added permanently in Windows Vista, Python 3.5
System > Control Panel > Advanced system settings > Advanced (tap) Environment Variables > System variables > (if you don't see PYTHONPATH in Variable column) (click) New > Variable name: PYTHONPATH > Variable value:
Please, write the directory in the Variable value. It is details of Blue Peppers' answer.
Fix Python Path issues when you switch from bash to zsh
I ran into Python Path problems when I switched to zsh from bash.
The solution was simple, but I failed to notice.
Pip was showing me, that the scripts blah blah or package blah blah is installed in ~/.local/bin which is not in path.
After reading some solutions to this question, I opened my .zshrc to find that the solution already existed.
I had to simply uncomment a line:
Take a look
I found a solution to do this in a anaconda environment here: https://datacomy.com/python/anaconda/add_folder_to_path/
Just:
conda develop /your_path
In Python 3.6.4 you can persist sys.path across python sessions like this:
import sys
import os
print(str(sys.path))
dir_path = os.path.dirname(os.path.realpath(__file__))
print(f"current working dir: {dir_path}")
root_dir = dir_path.replace("/util", '', 1)
print(f"root dir: {root_dir}")
sys.path.insert(0, root_dir)
print(str(sys.path))
I strongly suggest you use virtualenv and virtualenvwrapper otherwise you will clutter your path
Inspired by andrei-deusteanu answer, here is my version. This allows you to create a number of additional paths in your site-packages directory.
import os
# Add paths here. Then Run this block of code once and restart kernel. Paths should now be set.
paths_of_directories_to_add = [r'C:\GIT\project1', r'C:\GIT\project2', r'C:\GIT\project3']
# Find your site-packages directory
pathSitePckgs = os.path.join(os.path.dirname(os.__file__), 'site-packages')
# Write a .pth file in your site-packages directory
pthFile = os.path.join(pathSitePckgs,'current_machine_paths.pth')
with open(pthFile,'w') as pth_file:
pth_file.write('\n'.join(paths_of_directories_to_add))
print(pthFile)
After multiple bashing into wall. Finally resolved, in my CentOS 8 the pip3 was old, which was showing error to install the recent packages.
Now, I had downloaded the Python source package, which is Python-3.10.4 and installed the usual way, however the post-installation check generated errors in bash.
And I could not remove the existing Python, because that would break the CentOS desktop features.
Solution:
For building
./configure //don't not add --prefix=/usr, which you need to set proper care
make -j8
sudo make install
Now, as you have multiple Python installed, you can set alias python=python3
And for setting PYTHONPATH
export PYTHONPATH="/usr/local/bin/python3.10:/usr/local/lib/python3.10/lib-dynload:/usr/local/lib/python3.10/site-packages"
Don't add PYTHONHOME
For those who (like me) don't want to get too deeply involved in Python file management (which seems hopelessly overcomplicated), creating a .pth file works perfectly on my Windows 11 laptop (I'm using Visual Studio Code in Windows). So just go to the folder for your virtual environment site packages - there's mine:
Create a text file with a .pth extension - I called mine wheal.pth:
Add paths to it:
The best thing about this in VS Code is that import statements recognise this path (I had to exit VS Code and go back in), so now more typing # type: ignore to suppress linting warning messages!
on Mac :
user#terminal$ env PYTHONPATH=module_path python3
>>> import sys
>>> sys.path
['module_path', 'plus_other_python3_paths',...]
Shortest path between A <-> B is a straight line;
import sys
if not 'NEW_PATH' in sys.path:
sys.path += ['NEW_PATH']

Categories