为什么带尾随冒号的PYTHONPATH将当前目录添加到sys.path?

时间:2015-11-09 17:54:13

标签: python import pythonpath sys.path

考虑像这样的Python项目:

contains

在正常情况下,尝试从foo/ __init__.py scripts/ run.py demo.sh 包导入 如果您从项目的根目录运行脚本,则会失败,因为默认的Python 行为是添加调用Python解释器的脚本的目录 (不一定是当前目录)到foo。 (docs):

sys.path

然而,我最近注意到这样的进口正在我的盒子上工作,我 追踪它与PYTHONPATH相关的一些令人惊讶的行为。在我的Bash中 我已经为PYTHONPATH添加了一个目录:

python scripts/run.py

如果PYTHONPATH最初为空,那(有点草率,但常见) 命令的形式将留下一个尾随冒号:

export PYTHONPATH="/some/path:$PYTHONPATH"

我一直认为这个尾随标点没有影响,但它 似乎结尾的结肠是神秘成功的原因 进口。前导或尾随冒号(甚至是定义但空的PYTHONPATH) 将导致echo $PYTHONPATH /some/path: 包含空字符串 sys.path之前 模块加载,这反过来导致添加当前工作目录 到site

这是一个Python脚本和一个Bash脚本来演示。我也一样 使用Python 2.7和Python 3.3的行为。

Python脚本:sys.path

run.py

Bash脚本: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

demo.sh

我的问题

  • 我是否正确了解情况,或者我不知何故误入歧途?

  • 这是否记录在任何地方?我没找到任何东西。至少,我是 在此处发布此信息以防其他人。

  • 我是否一个人意外地发现这种行为?

1 个答案:

答案 0 :(得分:3)

修改冒号分隔的环境变量时,例如PYTHONPATH,PATH,CPATH,MANPATH,LD_LIBRARY_PATH,PKG_CONFIG_PATH等等......其中一些变量对尾随冒号有特殊意义,而其他变量则没有。

对于PYTHONPATH和PATH,如果变量先前未设置,我建议以不会意外引入尾随(或前导)冒号的方式预先添加(或追加)新目录:

export PYTHONPATH="/some/path${PYTHONPATH+":"}${PYTHONPATH-}"

(在MANPATH和INFOPATH的情况下,你想要引入一个尾部冒号,以便maninfo包含它们的默认搜索目录。)

说明:

    如果设置了PYTHONPATH,
  • ${PYTHONPATH+":"}会扩展为:,无论PYTHONPATH是否为空。
  • ${PYTHONPATH-}将扩展为PYTHONPATH的内容(如果已设置),但如果未设置PYTHONPATH,则${PYTHONPATH-}会扩展为空 - 就像通常的${PYTHONPATH}一样

    • ${PYTHONPATH-}${PYTHONPATH-""}相同,意思是替换"" (没有)当PYTHONPATH未设置时。
    • 我建议${PYTHONPATH-}超过${PYTHONPATH}的原因是,当{1}}未设置PYTHONPATH并且您的脚本已执行${PYTHONPATH-}以在未设置时引发错误时,set -u不会创建错误变量

有关${parameter+[word]}${parameter-[word]}机制的详细信息,请参阅"参数扩展"在http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

有关set -u的详细信息,请参阅" set"的说明。在http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set