【问题标题】:Generate non-zero exit code when IPython encounters an exception running a script当 IPython 遇到运行脚本的异常时生成非零退出代码
【发布时间】:2016-01-08 18:45:07
【问题描述】:

我想用 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

【问题讨论】:

标签: python bash ipython


【解决方案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 的前沿版本来解决,如下所示:

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

【讨论】:

    【解决方案2】:

    在 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
    

    【讨论】:

      猜你喜欢
      • 2013-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 2017-04-08
      • 2018-12-03
      • 1970-01-01
      相关资源
      最近更新 更多