0

I would like to get a full, descriptive error message from failed Python script executed with subprocess module.

I have a following script sub_script.py which fails and produces IndexError: pop from empty list error when executed on it's own:

# sub_script.py

empty_list = []
empty_list.pop()

I am calling sub_script.py from sub_test.py as follows:

# sub_test.py

import subprocess
import sys

print(str(subprocess.run([sys.executable, 'sub_script.py'],
                         check=True,
                         capture_output=True)))

However I am only getting subprocess.CalledProcessError error.

Traceback (most recent call last):
  File "/Users/my_user/Desktop/my_dir/sub_test.py", line 4, in <module>
    print(str(subprocess.run([sys.executable, 'sub_script.py'],
  File "/usr/local/Cellar/python@3.9/3.9.5/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/usr/local/opt/python@3.9/bin/python3.9', 'sub_script.py']' returned non-zero exit status 1.

I would like to see a full description of the error returned from sub_script.py (IndexError: pop from empty list) when it's executed with a subprocess in sub_test.py.

Is it possible to get full error when script executes and fails within subprocess.run?

verkter
  • 758
  • 4
  • 15
  • 29
  • This answers your question? https://stackoverflow.com/questions/24849998/how-to-catch-exception-output-from-python-subprocess-check-output/24850026 – T. Kelher Jun 16 '21 at 21:25
  • I tried it already, it still returns `subprocess.CalledProcessError` instead of `IndexError: pop from empty list` – verkter Jun 16 '21 at 21:26
  • 1
    Have you tried capturing `stdout` and `stderr` from `subprocess.run()`? – MattDMo Jun 16 '21 at 21:28
  • If you want to actually have an IndexException, you'll have to import the file and do it through python not subprocess, if you just want the output of the error, the link should work. – T. Kelher Jun 16 '21 at 21:29
  • I have to use subprocess, I cannot import file @T.Kelher – verkter Jun 16 '21 at 21:31
  • @MattDMo Yes, the output is the same as with `capture_output=True` – verkter Jun 16 '21 at 21:32
  • if I run 'subprocess.run([sys.executable, 'test.py'], check=True, capture_output=True)', and catch the exception with ' except subprocess.CalledProcessError as e:' I get "b'Traceback (most recent call last):\r\n File "C:\\Users\\Gebruiker\\Documents\\test\\test.py", line 2, in \r\n output[50]\r\nIndexError: list index out of range\r\n'" when I print(e.stderr). But that output is not enough you want to do try, and actually except the indexerror instead of subprocess.CalledProcessError? – T. Kelher Jun 16 '21 at 21:45

1 Answers1

2

Keep the return value of the subprocess.run call instead of immediately converting it to a str, and do not have check=True.

# main.py
import subprocess
import sys

command = [sys.executable, 'task.py']
outcome = subprocess.run(command, check=False, capture_output=True)
print(f"returncode = {outcome.returncode}")
if outcome.returncode != 0:
    # there was an error, we assume the traceback was printed to stderr
    print("there was an error :\n")
    print(outcome.stderr.decode("utf-8"))
# task.py
empty_list = []
empty_list.pop()

output :

returncode = 1
there was an error :

Traceback (most recent call last):
  File "task.py", line 2, in <module>
    empty_list.pop()
IndexError: pop from empty list
Lenormju
  • 4,078
  • 2
  • 8
  • 22