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
我想 运行 一个带有 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