IPython使用与shell不同的$ PATH环境

时间:2014-07-10 08:36:33

标签: python bash shell ipython zsh

我在IPython REPL中调用pip时遇到了一些问题,过了一段时间后我注意到IPython没有使用与我的shell相同的$ PATH环境。

$ echo $PATH
/Users/jimmy/dev/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin

$ ipython
In [1]: !echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin:/Users/jimmy/dev/anaconda/bin

它确实似乎扰乱了路径顺序,我不太清楚什么是错的。

我使用通过oh-my-zsh安装的ZSH作为shell,如果有帮助的话。

这是sys.path()返回的内容:

['',
 '/Users/jimmy/dev/anaconda/bin',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/sparsesvd-0.2.2-py2.7-macosx-10.5-x86_64.egg',
 '/Users/jimmy/dev/projects/pyresult',
 '/Users/jimmy/dev/work/gavagai/userdata',
 '/Users/jimmy/dev/work/gavagai/gavapi',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python27.zip',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-darwin',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-mac',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-tk',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-old',
 '/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-dynload',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/runipy-0.1.0-py2.7.egg',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/setuptools-3.6-py2.7.egg',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/PIL',
 '/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/IPython/extensions',
 '/Users/jimmy/.ipython']

这就是os.environ['PATH']返回的内容:

'/Users/jimmy/dev/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin'

两者似乎都按照正确的顺序排列。

感谢所有人的帮助。

2 个答案:

答案 0 :(得分:8)

总结和补充@holdenweb's helpful answer,特别是关于OS X:

  • 从IPython启动的子shell !非交互式 非登录用户默认的实例> shell - 即使IPython是从不同的 shell启动的。
    • 在幕后,子shell以path/to/default/shell -c ...
    • 开头
    • 要查看具体信息,请运行!ps -p $$ && :
  • echo $SHELL 始终告诉您默认 shell - 即使是从不同的 shell运行。

  • 来自非交互式非登录shell
  • 初始化文件

    • zsh:/etc/zshenv~/.zshenv
    • bash$BASH_ENV变量中指向的脚本(如果已定义)。
  • 正如所指出的,shell会根据是否加载不同/附加的初始化文件:

    • shell是登录 shell或不是
    • 一个交互式 shell或不是

    请注意,登录shell可以是交互式的,也可以不是,而且交互式shell可以是登录shell。

因此,在本案例中,可能两个附加的初始化文件被加载到交互式 shell中,解释了交互式shell和创建的子shell之间的行为差​​异通过IPython:

  • ~/.zprofile - 如果shell是 login shell - 如果zsh默认 shell,则会出现这种情况(在OS X上) ,在Terminal.app等终端中创建的默认shell的所有交互式实例都是登录shell。
  • ~/.zshrc

最后,在相关说明中,请注意在OS X上,NON-shell进程的默认$PATH为:

/usr/bin:/bin:/usr/sbin:/sbin  # Note the absence of /usr/local/bin.

且只有 shells 通过系统范围的初始化文件(调用/usr/local/bin)将/usr/libexec/path_helper(默认情况下为可扩展)添加到该文件中:

  • zsh
    • /etc/zshenv
    • 注意:对所有zsh实例生效。
  • bash(同样在sh调用时),ksh
    • /etc/profile
    • 注意:仅对LOGIN shell生效。

结果是:

  • 非shell应用只能看到默认的$PATH(特别是没有/usr/local/bin以及通过shell初始化文件添加的其他内容。)
  • 从登录shell启动的
  • bash / shksh非交互式非登录shell 也只能看到默认的$PATH 。例如,当Alfred等GUI命令行启动程序创建shell实例时,会发生这种情况。
  • zsh 未受影响,因为每个 /etc/zshenv实例都会读取zsh

答案 1 :(得分:6)

首先,sys.path与此无关;它只是Python解释器在导入模块时可以看到的位置列表,并不确定shell找到可执行程序的位置。但是,在该列表中可以看到PATH的一些元素,因为解释器使用其可执行文件的路径在sys.path上构建某些条目。

毫不奇怪,

os.environ['PATH']与运行IPython的环境中的$PATH变量相同。 !echo $PATH打印出IPython启动的子shell中的$PATH变量,以执行shell转义(!)。

一个可能的原因是IPython正在使用操作系统标准shell执行shell命令,该命令尚未定制为以zsh具有相同的方式设置其路径。您可以通过执行IPython命令!echo $SHELL来确认这一点。由于您确认不是这种情况,因此可以通过登录shell和交互式shell之间的差异来解释差异。

我不知道会告诉IPython使用另一个shell的配置项,但是可能有一个。作为一种解决方法,只需确保其他shell具有正确配置的路径,或者交互式shell也会看到您需要的环境。

请参阅@ mklement0对整个,血腥,凌乱细节的极其权威的答案。