356

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?

Vtik
  • 2,824
  • 1
  • 18
  • 35
John Howard
  • 50,339
  • 21
  • 44
  • 63

20 Answers20

486

If you're using bash (on a Mac or GNU/Linux distro), add this to your ~/.bashrc

export PYTHONPATH="${PYTHONPATH}:/my/other/path"
Acumenus
  • 41,481
  • 14
  • 116
  • 107
awesomo
  • 7,430
  • 2
  • 18
  • 23
  • 33
    This worked perfectly for me, but make sure the directory you point to has at the topmost __init__.py file in your directory structure. This wasn't perfectly clear for me at first. For example, I tried **export PYTHONPATH=$PYTHONPATH:/Users/joey/repos** but it did not work because my repos directory did not have \__init__.py. Going down one directory further: **/Users/joey/repos/specificRepo** did the trick. Now python can traverse any downward directory connected to the specificRepo directory that contains a __init__.py ! – Qiao Yi Mar 14 '13 at 14:29
  • 3
    this worked for me but could you explain where this PYTHONPATH variable is located? and how does "export PYTHONPATH" know to locate that exact file? – appleLover Jun 07 '13 at 17:23
  • 47
    remember after you edit ``~/.bashrc`` then run ``source ~/.bashrc`` see http://stackoverflow.com/questions/2518127/how-do-i-reload-bashrc-without-logging-out-and-back-in – b_dev Aug 13 '13 at 16:02
  • 2
    I think it's a bad idea to put `sudo su` at the start of your .bashrc file. [This post](http://askubuntu.com/questions/34530/executing-a-super-user-command-through-bashrc) agrees with me. On my system, at least, it's not even necessary. – LondonRob Apr 14 '14 at 10:00
  • This is the answer. – Aerin Jan 30 '18 at 05:30
  • Why does this make me think python deployment to production may be a pain the butt. – Paul Carlton Mar 10 '19 at 20:57
144

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.

Alex Martelli
  • 762,786
  • 156
  • 1,160
  • 1,345
  • 8
    Errata: separator on windows would a semicolon. If you need to override system paths on windows, setting via the GUI as a user environment variable may not be sufficient, as user variables are appended to system variables. In these cases, you'll need to resort to a startup script that makes the necessary adjustments. – Nathan Ernst Aug 04 '10 at 03:18
  • 1
    @Nathan, tx for the reminder on semicolon, but (if you're an admin of course) you _can_ set **system** env.vars on windows (plus, the OP is not asking how to **override** the path, just how to **append** to it, so, a user env.var will also be fine for that!-). – Alex Martelli Aug 04 '10 at 04:16
  • 1
    unfortunately I'm not an admin on my work PC, so I have to resort to such measures. :( – Nathan Ernst Aug 04 '10 at 22:13
  • "in Windows, you can do it through the system GUI for the purpose." -this did not work for me. I had to implement andrei deusteanu's solution below.. – juggler Aug 16 '20 at 04:05
93

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"
sth
  • 200,334
  • 49
  • 262
  • 354
  • I've tried this using Python 2.6 and it doesn't seem to work for me – Lorcan O'Neill Feb 26 '13 at 18:02
  • 4
    I just symlinked this directory to my own library directory and store all my scripts there. Worked fine. – firesofmay Mar 05 '13 at 06:08
  • Resolved to try it again after finding this topic again and managed to get it working as above this time! Upvoted and contrite apologies :) – Lorcan O'Neill Mar 07 '13 at 11:20
  • This works just perfectly, I was on the right track but the **`python -m site --user-site`** and **`(create the directory if it doesn't exist)`** parts were what I was missing to get it working. – Aurélien Ooms Mar 09 '13 at 21:33
  • in `2.7.4` this `python -m site --user-site` prints nothing to the screen – Ciro Santilli新疆棉花TRUMP BAN BAD May 06 '13 at 15:07
  • ok this worked in 2.7.4: `python -c $'import site\nprint site.USER_SITE'` – Ciro Santilli新疆棉花TRUMP BAN BAD May 06 '13 at 15:56
  • Should the SITEDIR (from above) folder change if using virtualenv? Cause for me it didn't change, but don't know if it's because my main Python install is in the PATH or if it's because the Python in virtualenv still uses that same folder as SITEDIR. – Gabriel Jun 14 '13 at 00:58
  • I did this, but for some reason, eclipse (the IDE I use) doesn't find the imports I make from files which are in folders I just made a .pth file for. I restarted eclipse but to no avail. – patapouf_ai Mar 25 '15 at 15:23
  • The python path is correctly added. When I execute print ';'.join(sys.path) the path shows up correctly, my problem is only that eclipse doesn't see the path and gives me an error when I try to import the library. – patapouf_ai Mar 25 '15 at 15:53
  • 1
    Do I need to take an additional step so python would recognize the added path to `somelib.pth`? If not, any guesses why this might not be working? – Miladiouss Apr 04 '18 at 07:13
51

This works on Windows

  1. On Windows, with Python 2.7 go to the Python setup folder.
  2. Open Lib/site-packages.
  3. Add an example.pth empty file to this folder.
  4. 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.

auserdude
  • 831
  • 6
  • 15
  • 3
    IMO, this is the best solution, since it does not depend on choice of shell or working environment. Works on linux as well, where the default python path is "/usr/local/lib/pythonX.Y/site-packages". If that doesn't work, try putting your .pth file to dist-packages directory instead. – matus Jul 28 '16 at 12:49
  • 2
    Windows 7, Python 3.6.5. This is the answer. As auserdude wrote: Create the "example.pth" in Python's Lib/site-packages folder and then add your path like so: C:\somefolder\anotherfolder\targetfolder – JayJay123 Jul 25 '18 at 08:52
  • 1
    excellent answer, also works with python 3.7 on windows 10, my windows 10 path is: "C:\Users\{usrName}\AppData\Local\Programs\Python\Python37-32\Lib" – Ali80 Nov 29 '18 at 14:43
  • 1
    Can confirm that it works for Python 3.6.7 on Windows 10. However, note that the path is appended to your PYTHONPATH with means that your appended module will not be found in the case of a name collision. – BramAppel Sep 11 '19 at 08:26
  • looks like this is basically equivalent to andrei deusteanu's answer. you will need administrative permission to save to that folder. I'm using blender 2.8, windows 10.. – juggler Aug 16 '20 at 04:17
27

In case anyone is still confused - if you are on a Mac, do the following:

  1. Open up Terminal
  2. Type open .bash_profile
  3. In the text file that pops up, add this line at the end: export PYTHONPATH=$PYTHONPATH:foo/bar
  4. Save the file, restart the Terminal, and you're done
entrepaul
  • 867
  • 2
  • 11
  • 23
22

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.

Blue Peppers
  • 3,314
  • 2
  • 19
  • 23
15

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.

Pierz
  • 4,579
  • 35
  • 45
10

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/
Zah
  • 4,923
  • 1
  • 20
  • 33
10

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.

Acumenus
  • 41,481
  • 14
  • 116
  • 107
Peter Piper
  • 3,072
  • 3
  • 28
  • 47
10

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
testsingh
  • 1,203
  • 1
  • 15
  • 24
7

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

boyangeor
  • 91
  • 2
  • 3
  • I did `echo PYTHONPATH` and nothing showed up! that means this PYTHONPATH haven't been initilised, so I just paste this line`export PYTHONPATH=$PYTHONPATH:/TensorFlow/models/research/object_detection` in my `~/.bashrc` file and `source ~/.bashrc ` it. Later, when I did ` echo $PYTHONPATH` it gave me `:/TensorFlow/models/research/object_detection`, Any suggestion on if I have done something wrong? – Anu Jan 22 '19 at 18:22
  • `export PYTHONPATH=/TensorFlow/models/research/object_detection`, when you are exporting PYTHONPATH for the first time you have to do it without the `${PYTHONPATH}:` part – boyangeor Jan 23 '19 at 16:12
  • Thanks, but whenever I reboot my computer the python path is getting reset to the one I set the 1st i.e `:/TensorFlow/models/research/object_detection` and removes the 2nd `export PYTHONPATH=$PYTHONPATH:/TensorFlow/models/research/slim`. any suggestions on that, how to fix it? – Anu Jan 24 '19 at 17:22
6

Just to add on awesomo's answer, you can also add that line into your ~/.bash_profile or ~/.profile

Christian Specht
  • 33,837
  • 14
  • 123
  • 176
janex
  • 489
  • 4
  • 13
4

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))
  • 1
    I did this manually (went to arnaud's page..). I had to run my text editor as administrator, and then re-start blender to see the changes.. so I suppose, in principle, if there's a way to improve this answer, or the code, it's to observe the requirement of administrator privaledges, and provide an appropriate solution. that's above my pay-grade (in the sense that more experienced people will have opinions on this.. I leave it to them!) XD – juggler Aug 16 '20 at 04:00
  • 1
    You can avoid the need for administrator rights (and this entire path searching logic) by writing your .pth file to the directory returned by `python -m site --user-site`. Also known as `python -c "import site; print(site.USER_SITE)"`. You cannot assume that this user-site directory will exist, but you can create it. – Amit Naidu Oct 13 '20 at 20:11
  • Brilliant, this code helped me create something for my requirements. Cheers!!! https://stackoverflow.com/a/66372128/2007153 – DougR Feb 25 '21 at 16:08
4

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.

Caio Oliveira
  • 1,139
  • 11
  • 22
3

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.

wpmoradi
  • 31
  • 3
  • I know the post is old but if you could explain to me what source command is? – abdelhamed abdin Sep 02 '20 at 22:49
  • 1
    @abdelhamedabdin The source command reads and executes commands from the file specified as its argument in the current shell environment. It is useful to load functions, variables, and configuration files into shell scripts. – wpmoradi Sep 07 '20 at 19:56
2

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.

Cloud Cho
  • 933
  • 11
  • 16
0

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

Rubber Duck
  • 3,126
  • 1
  • 25
  • 39
0

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

Screenshot from 2020-10-07 13-38-17

aahnik
  • 512
  • 2
  • 13
0

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)
DougR
  • 2,205
  • 1
  • 18
  • 27
-4

Shortest path between A <-> B is a straight line;

import sys
if not 'NEW_PATH' in sys.path:
  sys.path += ['NEW_PATH']
Al Kari
  • 79
  • 6