我在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'
两者似乎都按正确的顺序排列.
感谢所有人的帮助.
首先,sys.path
与此无关; 它只是Python解释器在导入模块时可以看到的位置列表,并不确定shell找到可执行程序的位置.PATH
但是,在该列表中可以看到一些元素,因为解释器使用其可执行文件的路径来构建某些条目sys.path
.
os.environ['PATH']
毫不奇怪,与$PATH
运行IPython的环境中的变量相同.!echo $PATH
打印出$PATH
由IPython启动的子shell中的变量来执行shell escape(!
).
一个可能的原因是IPython正在使用操作系统标准shell执行shell命令,该命令尚未经过定制,以与您的路径相同的方式设置其路径zsh
.您可以通过执行IPython命令来确认这一点!echo $SHELL
.由于您确认不是这种情况,因此可以通过登录shell和交互式shell之间的差异来解释差异.
我不知道一个配置项会告诉IPython使用另一个shell,但它可能有一个.作为解决方法,只需确保其他shell具有正确配置的路径,或者交互式shell也可以查看所需的环境.
请参阅@ mklement0对整个,血腥,凌乱细节的极其权威的答案.
总结和补充@ holdenweb的有用答案,特别是关于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和IPython创建的子shell之间的行为差异:
~/.zprofile
- 如果shell是登录 shell - 如果zsh
是默认 shell 将是这种情况(在OS X上,在终端中创建的默认shell的所有交互式实例,例如Terminal.app
登录shell).
~/.zshrc
最后,在相关说明中,请注意在OS X上$PATH
,NON-shell进程的默认值为:
/usr/bin:/bin:/usr/sbin:/sbin # Note the absence of /usr/local/bin.
并且只有shell/usr/local/bin
通过系统范围的初始化文件(该调用/usr/libexec/path_helper
)添加(默认情况下,可扩展);
zsh
:
/etc/zshenv
注意:对所有zsh
实例生效.
bash
(同样当作为援引sh
)ksh
:
/etc/profile
注意:仅对LOGIN shell生效.
结果:
非shell应用程序仅查看默认值$PATH
(特别是没有/usr/local/bin
和通过shell初始化文件进行的其他添加).
bash
/ sh
和ksh
非交互式非登录shell 不是从登录shell启动也只看到默认的$PATH
.例如,当诸如Alfred的 GUI命令行启动程序创建shell实例时,就会发生这种情况.
zsh
是不是受到影响,因为/etc/zshenv
通过阅读每一个 zsh
实例.