0

I'm working on a terminal that can call other programs like any other terminal. I'm using subprocess for it, on Windows. I'm running into 2 issues.

First: Currently, I'm using OSError for all errors raised when using subprocess.Popen.

The code for it is here:

try:
    subprocess.Popen([command])
except OSError:
    print("'" + command[0] + "' is not recognised as a command, program or bterm file.")

When I type python, it opens command-line python correctly. When I type asdfa, it returns the error. The problem is, when I type python non-existent-file.py I get the same error, when the child argument was the issue.

I want the terminal to return (null): can't open file 'test': [Errno 2] No such file or directory like when it's called from cmd or bash.

How can I distinguish between these 2 errors, while keeping my custom error message for when the file doesn't exist?

Second: Whenever I pass multi-word args into subprocess.Popen or subprocess.call I automatically get that error, which I don't get using os.system()

I don't want to use os.system because I can't raise custom errors with it.

What am I doing wrong?

Auxilor
  • 49
  • 1
  • 8
  • possible duplicate of this? https://stackoverflow.com/questions/24849998/how-to-catch-exception-output-from-python-subprocess-check-output – Akhil Batra May 18 '19 at 21:09
  • @AkhilBatra Not quite, I still want my custom error to print when the file doesn't exist, instead of just returning an error from cmd – Auxilor May 18 '19 at 21:11
  • you can try redirecting subprocess output to stderr and catch error based on the return code. Similar to this - https://stackoverflow.com/questions/16198546/get-exit-code-and-stderr-from-subprocess-call – Akhil Batra May 18 '19 at 21:17
  • @AkhilBatra I get error code 2 both times when returning the error using ```except OSError as ex print(ex) ``` – Auxilor May 18 '19 at 21:22
  • That's a bummer. – Akhil Batra May 18 '19 at 21:24

2 Answers2

1

Exceptions in subprocess calls:

Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent. Additionally, the exception object will have one extra attribute called child_traceback, which is a string containing traceback information from the child’s point of view.

The most common exception raised is OSError. This occurs, for example, when trying to execute a non-existent file. Applications should prepare for OSError exceptions.

A ValueError will be raised if Popen is called with invalid arguments.

check_call() and check_output() will raise CalledProcessError if the called process returns a non-zero return code.

You can find more at: https://docs.python.org/2/library/subprocess.html#exceptions

As well as you can find the Exception Heirarchy at: https://docs.python.org/2/library/exceptions.html#exception-hierarchy

try:
    output = subprocess.check_output("\\test.exe')
except subprocess.CalledProcessError as e:
    print("Something Fishy... returncode: " + e.returncode + ", output:\n" + e.output)
else:
    print("Working Fine:\n" + output)
shyamzzp
  • 115
  • 7
1

You could test for the existence of the executable first with the help of shutil.which.

if shutil.which(commands[0]):
    try:
        subprocess.Popen([commands])
    except OSError as err:
        print(err)
else:
    print("'{}' is not recognised as a command, program or bterm file.".format(commands[0])

The documentation has a great deal of info however: https://docs.python.org/dev/library/subprocess.html which may be helpful.

Edit: showed how to capture output, thanks to Auxilor

0x76
  • 185
  • 3
  • 9
  • 1
    you can capture the output with this ```python except OSError as ex: ``` ```python print(ex) ``` – Auxilor May 18 '19 at 21:30
  • problem is, with this one, you end up with everything inputted into something like cmd or python being treated as an input into my terminal – Auxilor May 18 '19 at 22:02