考虑一个像这样的 Python 项目:
foo/
__init__.py
scripts/
run.py
demo.sh
通常情况下,如果您从项目根目录运行脚本,则尝试从foo
包导入将失败,因为默认的Python行为是将调用Python解释器的脚本所在目录(而不一定是当前目录)添加到sys.path
。(文档):
python scripts/run.py
然而,最近我注意到这样的导入在我的电脑上可以正常工作,经过追踪后发现与PYTHONPATH相关的一些令人惊讶的行为。在我的Bash配置文件中,我已经将一个目录添加到了PYTHONPATH中:
export PYTHONPATH="/some/path:$PYTHONPATH"
如果PYTHONPATH最初为空,则该命令的形式(有些松散,但通常可见)将留下一个尾随冒号:
echo $PYTHONPATH
/some/path:
我曾经认为这个结尾标点符号没有影响,但事实上这个冒号是神秘成功导入的原因。前置或后置的冒号(甚至是定义但为空的PYTHONPATH)会导致在site模块加载之前,sys.path包含一个空字符串,从而将当前工作目录添加到sys.path中。以下是Python脚本和Bash脚本示例。我在Python 2.7和Python 3.3中都得到了相同的结果。
Python脚本: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脚本: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
我的问题:
我是否正确理解了情况,还是我走错了路?
这有文件记录吗?我没有找到任何信息。至少,我在这里发布这些信息,以防对他人有所帮助。
我一个人认为这种行为出乎意料吗?
export "PATH=$PATH:"
允许在 Linux 上执行本地路径下的命令。Python 的工作方式也是如此。 - tdelaney