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

时间:2016-01-08 18:45:08

标签: python bash ipython

我想用IPython运行一个python脚本,并能够判断脚本是否成功(一直运行)还是不成功(引发异常)。

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

如何在使用IPython运行脚本时禁用此行为?

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

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

fail.py

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

使用IPython运行脚本时,异常将打印到stdout,返回值为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运行脚本时,会捕获异常并将回溯打印到stdout,然后IPython退出并返回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

2 个答案:

答案 0 :(得分:2)

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

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

暂时可以通过安装ipython的最新版本来解决这个问题,如下所示:

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

答案 1 :(得分:1)

您似乎无法在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