Consider a Python project like this:
foo/
__init__.py
scripts/
run.py
demo.sh
Under normal circumstances, attempting to import from the foo
package will
fail if you run the script from the root of the project, because default Python
behavior is to add the directory of script invoking the Python interpreter
(and not necessarily the current directory) to sys.path
.
(docs):
python scripts/run.py
However, I recently noticed that such imports were working on my box, and I tracked it down to some surprising behavior related to PYTHONPATH. In my Bash profile I had added a directory to PYTHONPATH:
export PYTHONPATH="/some/path:$PYTHONPATH"
If PYTHONPATH is initially empty, that (somewhat sloppy, but commonly seen) form of the command will leave a trailing colon:
echo $PYTHONPATH
/some/path:
I had always assumed that this trailing punctuation had no impact, but it
appears that the trailing colon was the cause of the mysteriously successful
import. Leading or trailing colons (or even a defined but empty PYTHONPATH)
will result in sys.path
containing an empty string before the site
module loads, which in turn leads to the current working directory being added
to sys.path
.
Here are a Python script and a Bash script to demonstrate. I got the same behavior using both Python 2.7 and Python 3.3.
Python script: run.py
:
import sys, os
pp = os.environ.get('PYTHONPATH')
try:
import foo
print 'OK'
assert os.getcwd() in sys.path
assert pp == '' or pp.startswith(':') or pp.endswith(':')
except Exception:
print 'FAIL'
assert os.getcwd() not in sys.path
assert pp is None
Bash script: demo.sh
:
# Import fails.
unset PYTHONPATH; python scripts/run.py
# Import succeeds -- to my surprise.
PYTHONPATH='' python scripts/run.py
PYTHONPATH='/tmp:' python scripts/run.py
PYTHONPATH=':/tmp' python scripts/run.py
My questions:
Am I understanding the situation correctly, or have I somehow gone astray?
Is this documented anywhere? I did not find anything. At a minimum, I am posting this information here in case it will help others.
Am I alone in finding this behavior unexpected?
export "PATH=$PATH:" lets
commands in the local path be executed on linux. Python is working the same way. – Damali