conner.xyz
conner.xyz

Reputation: 7275

Subprocess not raising CalledProcessError

I have a script that loops through a few file paths in order execute some other python and bash scripts using subprocess.

I know that these scripts will occasionally fail, and I want to catch the exception and stop the loop/exit the calling script. This seems like it should be very simple – but I'm going nuts getting it to work.

I've tried a number of subprocess methods, and I can't seem to catch a CalledProcessError from any of them (call, check_call, check_output Popen).

# 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

Now imagine the first script throws an exception. I want it to cause the calling script to exit.

# w.py

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

Instead none of the exceptions are caught by the calling script and the calling script continues the loop.

$ 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

Upvotes: 2

Views: 1561

Answers (3)

Resq
Resq

Reputation: 301

I had exactly the same issue and started debugging into subprocess.py.

Than I realized that I never reached a breakpoint in the subprocess.run() function.

And than it came to my mind, that I did install the subprocess.run package for python35 a time ago.

After deleting the package it worked again.

Upvotes: 2

SeF
SeF

Reputation: 4160

Funnily enough I wanted to do exactly what is happening to you, and I could not, because I was not using try except (I am in python 2.7). What happen if you simply do that?

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

As far as I can understand of this mysterious subprocess, if you want the program to stop you have to disentangle from the try except structure, as subprocess.check_output will stop by default when the exit status is 1.

Upvotes: 0

Alex Hall
Alex Hall

Reputation: 36023

Looks like ipython doesn't return a non-zero exit code on exceptions, which is required for subprocess.check_output to raise a CalledProcessError. Just use 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

Alternatively, just import the script or use execfile or something similar.

Upvotes: 0

Related Questions