考虑一个这样的 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)将导致在模块加载之前sys.path
包含一个空字符串
,这反过来又导致当前工作目录被添加到.site
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
我的问题:
我是否正确理解了情况,或者我是否误入歧途?
这在任何地方都有记录吗?我什么也没找到。至少,我会在此处发布此信息,以防对其他人有所帮助。
只有我一个人发现这种行为出乎意料吗?