IPython 遇到异常时生成非零退出代码 运行 脚本

Generate non-zero exit code when IPython encounters an exception running a script

我想 运行 一个带有 IPython 的 python 脚本,并且能够判断脚本是成功的(运行 一直)还是不成功(出现异常)。

通常可以通过检查命令的 return 值来判断命令是否成功,其中约定为 0 表示成功,其他整数表示错误(该值表示错误)。这是 运行ning 脚本与 python script.py 时的行为,但是当使用 ipython script.py 时,IPython 会自动捕获错误并且(毫无帮助)returns 退出代码 0 .

如何在 运行 将脚本与 IPython 连接时禁用此行为?

顺便说一下,我需要 运行 IPython 中的脚本而不是 Python,因为该脚本是从 IPython 笔记本 (.ipynb) 生成的并且包含一些 IPython 魔术命令。

这是一个最小的工作示例。

fail.py

#! /usr/bin/env python
mytext = 'Hello World!'
if __name__=="__main__":
    print(missing_variable)

当 运行 使用 IPython 连接脚本时,异常会打印到标准输出并且 return 值为 1,正确表示脚本失败。

~$ python fail.py
Traceback (most recent call last):
  File "fail.py", line 4, in <module>
    print(missing_variable)
NameError: name 'missing_variable' is not defined
~$ echo $?
1

当 运行 使用 IPython 连接脚本时,异常被捕获并将回溯打印到标准输出,然后 IPython 退出并且 returns 0(这不可取,因为脚本没有成功)。

~$ ipython fail.py
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
~/fail.py in <module>()
      2 mytext = 'Hello World!'
      3 if __name__=="__main__":
----> 4     print(missing_variable)

NameError: name 'missing_variable' is not defined
~$ echo $?
0

您似乎无法在 IPython 中执行此操作(有关详细信息,请参阅 this discussion)。您可以做的是使用 try/except,然后使用 sys.exit(code_number) 设置所需的退出代码。您还可以使用 traceback 模块以 Python 解释器的方式打印出堆栈跟踪。所以您的代码可能如下所示:

import sys, traceback
mytext = 'Hello World!'

if __name__=="__main__":
    try:
        print(missing_variable)
    except:
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)

然后运行这个:

~$ ipython fail.py

理论上应该产生堆栈跟踪以及退出代码 1:

~$ echo $?
1

正如@chrisaycock 和@vrs 所指出的,ipython GitHub 页面上有一个 issue discussing this problem

此外,该问题已得到解决并修复 merged into the ipython main code base,但是该修复太新,无法出现在 ipython 的任何已发布版本中。撰写本文时 ipython 的最新发布版本是 v4.0.1,解决方案应该在下一个版本 v4.1.0 中。

目前,这可以通过安装 ipython 的 bleeding-edge 版本来解决,如下所示:

virtualenv --no-site-packages -p /usr/bin/python2.7 tmp-env
source tmp-env/bin/activate
pip install git+git://github.com/ipython/ipython.git@master

我们可以看到不良行为现已修复:

(tmp-env)~$ pip freeze
argparse==1.2.1
decorator==4.0.6
ipython==4.1.0.dev0
ipython-genutils==0.1.0
path.py==8.1.2
pexpect==4.0.1
pickleshare==0.5
ptyprocess==0.5
simplegeneric==0.8.1
traitlets==4.0.0
wsgiref==0.1.2
(tmp-env)~$ ipython fail.py 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
~/fail.py in <module>()
      2 mytext = 'Hello World!'
      3 if __name__=="__main__":
----> 4     print(missing_variable)

NameError: name 'missing_variable' is not defined
(tmp-env)~$ echo $?
1