这里有两个问题。
第一个比__future__ 语句更通用:至少在我的测试中,ipython 1.0.0 及更早版本根本不处理PYTHONSTARTUP 环境变量。你可以很容易地看到这一点:
$ echo -e 'print "PYTHONSTARTUP!"\n' > pythonstartup.py
$ PYTHONSTARTUP=./pythonstartup.py ipython
没有额外的打印出来。
#2706 建议应该这样做,#3569 对其进行了修补,并且 1.1.0 似乎是第一个更改的版本。
因此,修复是升级到 1.1.0。或者,如果您坚持使用旧版本,请执行 #2706 中的建议,并将其添加到您的第一个 $IPYTHONDIR/profile_default/startup/*py 文件中:
import os
if os.environ['PYTHONSTARTUP']:
execfile(os.environ['PYTHONSTARTUP'])
但是,这仍然不能解决问题。
$PYTHONSTARTUP 的运行方式(由您显式运行或由 iPython 隐式运行)等效于 exec。它确实将适当的globals 明确地赋予exec,从而确保您最终得到可用的print_function 元组……但这不会影响解析器。 (比较在交互式 shell 中键入 exec('from __future__ import print_function)`。)
对于上述启动文件、向后兼容的ipython.rc 文件(如果您启用了该文件)以及应该在您的交互式环境中执行的任何其他文件也是如此——它们实际上是只是 exec'd 在您的 globals 中,这并不完全相同。
即使是作为exec_files 机制的一部分在您的ipython_config.py 或其他应用程序配置脚本中执行的文件也会以这种方式处理。
但是,作为exec_lines 机制的一部分执行的行不是。所以,这就是解决方案。
编辑或创建~/.ipython/profile_default/ipython_config.py。 (如果您使用不同的配置文件、ipythondir、应用程序名称等,您大概知道,并且知道如何调整。)
如果它不存在,添加这一行:
c = get_config()
然后添加这个:
c.InteractiveShellApp.exec_lines = ['from __future__ import print_function']
更多详情请见Configuring the ipython command line application。
如果你真的想这样做,你可以这样做:
import os
try:
# Make sure to pop it so it won't get exec'd later in the startup
pythonstartup = os.environ.pop('PYTHONSTARTUP')
with open(pythonstartup) as f:
c.InteractiveShellApp.exec_lines.append(list(f))
except KeyError:
pass
但这看起来很老套。