164

How can I make any use of PYTHONPATH? When I try to run a script in the path the file is not found. When I cd to the directory holding the script the script runs. So what good is the PYTHONPATH?

$ echo $PYTHONPATH
:/home/randy/lib/python

$ tree -L 1 '/home/randy/lib/python' 
/home/randy/lib/python
├── gbmx_html.py
├── gbmx.py
├── __init__.py
├── __pycache__
├── scripts
└── yesno.py

$ python gbmx.py -h
python: can't open file 'gbmx.py': [Errno 2] No such file or directory

$ cd '/home/randy/lib/python'

After cd to the file directory it runs ..

$ python gbmx.py -h
usage: gbmx.py [-h] [-b]

Why can I not make any use of the PYTHONPATH?

raphael
  • 2,762
  • 5
  • 26
  • 55
Randy Skretka
  • 3,488
  • 3
  • 22
  • 14
  • 1
    Can we change the title of this post? It is not actually asking for an explanation of `PYTHONPATH`. –  Oct 18 '19 at 01:00
  • Edited title because this is the first thing that shows up when googling `PYTHONPATH` – raphael Dec 10 '19 at 19:57

5 Answers5

199

I think you're a little confused. PYTHONPATH sets the search path for importing python modules, not for executing them like you're trying.

PYTHONPATH Augment the default search path for module files. The format is the same as the shell’s PATH: one or more directory pathnames separated by os.pathsep (e.g. colons on Unix or semicolons on Windows). Non-existent directories are silently ignored.

In addition to normal directories, individual PYTHONPATH entries may refer to zipfiles containing pure Python modules (in either source or compiled form). Extension modules cannot be imported from zipfiles.

The default search path is installation dependent, but generally begins with prefix/lib/pythonversion (see PYTHONHOME above). It is always appended to PYTHONPATH.

An additional directory will be inserted in the search path in front of PYTHONPATH as described above under Interface options. The search path can be manipulated from within a Python program as the variable sys.path.

http://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH

What you're looking for is PATH.

export PATH=$PATH:/home/randy/lib/python 

However, to run your python script as a program, you also need to set a shebang for Python in the first line. Something like this should work:

#!/usr/bin/env python

And give execution privileges to it:

chmod +x /home/randy/lib/python/gbmx.py

Then you should be able to simply run gmbx.py from anywhere.

Pedro Werneck
  • 40,902
  • 7
  • 64
  • 85
  • 2
    Thanks friend. I am still ironing this out. My script does succeed in importing my modules from my custom PYTHONPATH. And now I understand the difference: it is all about script vs. module; command script call vs. python import. Yes, I will in fact use `export PATH=$PATH:/home/etc` – Randy Skretka Nov 11 '13 at 23:35
60

You're confusing PATH and PYTHONPATH. You need to do this:

export PATH=$PATH:/home/randy/lib/python 

PYTHONPATH is used by the python interpreter to determine which modules to load.

PATH is used by the shell to determine which executables to run.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Richard
  • 2,994
  • 1
  • 19
  • 31
39

PYTHONPATH only affects import statements, not the top-level Python interpreter's lookup of python files given as arguments.

Needing PYTHONPATH to be set is not a great idea - as with anything dependent on environment variables, replicating things consistently across different machines gets tricky. Better is to use Python 'packages' which can be installed (using 'pip', or distutils) in system-dependent paths which Python already knows about.

Have a read of https://the-hitchhikers-guide-to-packaging.readthedocs.org/en/latest/ - 'The Hitchhiker's Guide to Packaging', and also http://docs.python.org/3/tutorial/modules.html - which explains PYTHONPATH and packages at a lower level.

codedstructure
  • 796
  • 7
  • 16
  • Point taken. In this particular case adding to PYTHONPATH seems to work out nicely though. As one user on one machine I can well make use and reuse of some already written .py code. – Randy Skretka Nov 11 '13 at 23:51
  • 1
    I honestly do not think installing things in system dependent paths, with root access required, is a better idea than using `PYTHONPATH`. I don't count any more how many times I've had to deal with a rudimentary Python program that insisted on the `pip install` thing where I was a regular user on a host not only without root access (I know pip can do local installation) but also without pip. Here is an advice to everyone distributing Python software -- try to install your own software on a vanilla Linux host where you don't have root access and only core Python distribution without pip, first. – Armen Michaeli Apr 27 '18 at 09:02
5

With PYTHONPATH set as in your example, you should be able to do

python -m gmbx

-m option will make Python search for your module in paths Python usually searches modules in, including what you added to PYTHONPATH. When you run interpreter like python gmbx.py, it looks for particular file and PYTHONPATH does not apply.

Tigran Saluev
  • 3,351
  • 2
  • 26
  • 40
3

I think you're mixed up between PATH and PYTHONPATH. All you have to do to run a 'script' is have it's parental directory appended to your PATH variable. You can test this by running

which myscript.py

Also, if myscripy.py depends on custom modules, their parental directories must also be added to the PYTHONPATH variable. Unfortunately, because the designers of python were clearly on drugs, testing your imports in the repl with the following will not guarantee that your PYTHONPATH is set properly for use in a script. This part of python programming is magic and can't be answered appropriately on stackoverflow.

$python
Python 2.7.8 blahblahblah
...
>from mymodule.submodule import ClassName
>test = ClassName()
>^D
$myscript_that_needs_mymodule.submodule.py
Traceback (most recent call last):
  File "myscript_that_needs_mymodule.submodule.py", line 5, in <module>
    from mymodule.submodule import ClassName
  File "/path/to/myscript_that_needs_mymodule.submodule.py", line 5, in <module>
    from mymodule.submodule import ClassName
ImportError: No module named submodule
W4t3randWind
  • 631
  • 1
  • 7
  • 16