【问题标题】:Subprocess not raising CalledProcessError子进程未引发 CalledProcessError
【发布时间】:2016-09-22 08:26:00
【问题描述】:

我有一个脚本,它遍历几个文件路径,以便使用子进程执行一些其他 python 和 bash 脚本。

我知道这些脚本偶尔会失败,我想捕获异常并停止循环/退出调用脚本。这看起来应该很简单——但我要让它发挥作用。

我尝试了许多子流程方法,但我似乎无法从其中任何中捕获 CalledProcessError(callcheck_callcheck_outputPopen) .

# calling.py

for script in ['w', 'x', 'y']:
    try:
        subprocess.check_output('ipython {}.py'.format(script).split())
    except subprocess.CalledProcessError as e:
        print "Caught CalledProcessError"
        raise
    except Exception as e:
        print "Caught some other exception"
        raise

现在想象第一个脚本抛出异常。我希望它导致调用脚本退出。

# w.py

print "w"
a = {}
a[0]  # KeyError

相反,调用脚本不会捕获任何异常,调用脚本会继续循环。

$ ipython calling.py
w
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/Users/h138124/git/exceptional/w.py in <module>()
      1 print "w"
      2 a = {}
----> 3 a[0]

KeyError: 0
x
y

【问题讨论】:

  • 你为什么使用 ipython 来运行文件?还有什么操作系统?
  • @PadraicCunningham 我正在使用 ipython,因为机器上的 python 安装已过时。我正在登录一个我不管理的集群上的名称节点,所以我正在使用它。我用 python 得到了同样的结果。
  • @PadraicCunningham 在 OS X 和 Windows 7 上的结果也相同。
  • 如何登录机器?我根本无法在 linux 上复制它
  • @PadraicCunningham 我之前打错了。我在 OS X 和 Linux (CentOS 6.6) 上运行过它。我正在使用 Windows 7 VM 中的 cygwin 通过 ssh 登录(由于愚蠢的 Azure VPN 客户端,我必须这样做)。

标签: python bash python-2.7 exception subprocess


【解决方案1】:

我遇到了完全相同的问题并开始调试到 subprocess.py。

然后我意识到我从未在 subprocess.run() 函数中到达断点。

我想到的是,我确实在前一段时间为 python35 安装了 subprocess.run 包。

删除包后它再次工作。

【讨论】:

    【解决方案2】:

    看起来ipython 不会在异常时返回非零退出代码,这是subprocess.check_output 引发CalledProcessError 所必需的。只需使用python

    $ cat test.py 
    1/0
    $ python test.py 
    Traceback (most recent call last):
      File "test.py", line 1, in <module>
        1/0
    ZeroDivisionError: integer division or modulo by zero
    $ echo $?
    1
    $ ipython test.py
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
    /Users/alexhall/Dropbox/python/sandbox/test.py in <module>()
    ----> 1 1/0
    
    ZeroDivisionError: integer division or modulo by zero
    $ echo $?
    0
    

    或者,只需导入脚本或使用execfile 或类似的东西。

    【讨论】:

    • 有趣。很高兴知道这一点——尽管它不能解决问题。我使用 python 得到了相同的结果(没有捕获异常并且循环继续)。
    • @conner.xyz 你能复制我的结果吗? python是否有异常脚本的非零返回码?
    • 是的,我可以复制您的结果(python 返回 1,ipython 返回 0),但它不会影响在一个脚本运行另一个脚本时捕获异常。
    • 尝试subprocess.call 并打印返回值(应该是退出代码)。
    • 是0。不管我用python还是ipython。它显示 KeyError 但实际上并未捕获任何异常。这很奇怪。我将尝试将被调用者脚本包装在 main 中并按照您的建议导入。
    【解决方案3】:

    有趣的是,我想做你正在发生的事情,但我做不到,因为我没有使用 try except(我在 python 2.7 中)。 如果你只是这样做会发生什么?

    for script in ['w', 'x', 'y']:
        out = subprocess.check_output('ipython {}.py'.format(script).split())
        print(out)
    

    据我所知,这个神秘的子进程,如果你想让程序停止,你必须从try except结构中解开,因为当退出状态为1时,subprocess.check_output默认会停止。

    【讨论】:

      猜你喜欢
      • 2013-02-25
      • 2014-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2020-12-28
      • 2013-01-24
      • 2012-08-14
      相关资源
      最近更新 更多