1

How do I handle a subprocess.run() error in Python? For example, I want to run cd + UserInput with subprocess.run(). What if the user types in a directory name which does not exist? How do I handle this type of error?

Tomerikoo
  • 15,737
  • 15
  • 35
  • 52
GameCube
  • 23
  • 2
  • 2
    Running `cd` in `subprocess.run()` is a bad idea. Look at using the `cwd=` kyword parameter to `run()` instead, then you can catch `FileNotFoundError` if the diectory doesn't exist. – match Dec 28 '21 at 15:50
  • Does this answer your question? [Subprocess changing directory](https://stackoverflow.com/questions/21406887/subprocess-changing-directory) – Tomerikoo Dec 28 '21 at 16:02
  • You probably want to use [`os.chdir`](https://docs.python.org/3/library/os.html#os.chdir). There is no point in starting a process just to change its own directory and immediately exit... – Tomerikoo Dec 28 '21 at 16:04

3 Answers3

3

As @match has mentioned, you can't run cd as a subprocess, because cd isn't a program, it's a shell built-in command.

But if you're asking about any subprocess failures, besides cd:

try:
    subprocess.run(command_that_might_not_exist)  # like ['abcd']
except Exception:
    # handle the error
result = subprocess.run(command_that_might_fail)  # like ['ls', 'abcd/']
if result.returncode != 0:
    # handle the error
Expurple
  • 737
  • 4
  • 11
  • *"you can't run cd as a subprocess, because cd isn't a program, it's a shell built-in command."* - you can run `subprocess.run("cd", shell=True)`, but that would just be pointless... – Tomerikoo Dec 28 '21 at 16:07
  • The only way the first example can fail is if the operating system can't find or can't execute `command_that_might_not_exist` – tripleee Dec 28 '21 at 16:35
  • @tripleee, you are correct. `command_that_might_fail` is more common – Expurple Dec 28 '21 at 16:38
0

There is no way running cd in a subprocess is useful. The subprocess will change its own directory and then immediately exit, leaving no observable change in the parent process or anywhere else.

For the same reason, there is no binary command named cd on most systems; the cd command is a shell built-in.

Generally, if you run subprocess.run() without the check=True keyword argument, any error within the subprocess will simply be ignored. So if /bin/cd or a similar command existed, you could run

# purely theoretical, and utterly useless
subprocess.run(['cd', UserInput])

and simply not know whether it did anything or not.

If you do supply check=True, the exception you need to trap is CalledProcessError:

try:
    # pointless code as such; see explanation above
    subprocess.run(['cd', UserInput], check=True)
except subprocess.CalledProcessError:
    print('Directory name %s misspelled, or you lack the permissions' % UserInput)

But even more fundamentally, allowing users to prod the system by running arbitrary unchecked input in a subprocess is a horrible idea. (Allowing users to run arbitrary shell script with shell=True is a monumentally, catastrophically horrible idea, so let's not even go there. Maybe see Actual meaning of shell=True in subprocess)

A somewhat more secure approach is to run the subprocess with a cwd= keyword argument.

# also vaguely pointless
subprocess.run(['true'], cwd=UserInput)

In this case, you can expect a regular FileNotFoundError if the directory does not exist, or a PermissionError if you lack the privileges.

You should probably still add check=True and be prepared to handle any resulting exception, unless you specifically don't care whether the subprocess succeeded. (There are actually cases where this makes sense, like when you grep for something but are fine with it not finding any matches, which raises an error if you use check=True.)

Perhaps see also Running Bash commands in Python

tripleee
  • 158,107
  • 27
  • 234
  • 292
-2

You might use a try and expect block to handle exceptions.

Pythonaire
  • 33
  • 3
  • The error is raised by the process, not by the Python code... – Tomerikoo Dec 28 '21 at 16:01
  • @Tomerikoo, attempts to run a non-existing program actually raise a Python exception from `run()`. But I get what you're talking about – Expurple Dec 28 '21 at 16:16
  • @Expurple I was assuming the command is valid and the error comes from within said command/process. I was also assuming that this is the core of the question asked. How to handle the error the command `cd` might raise from an invalid argument, not how to actually run `cd`... – Tomerikoo Dec 28 '21 at 16:19
  • to find out what the problem is, try/except is a good way. Whatever the sub procedure do, the failure it raised, can be found by using python exceptions. – Pythonaire Dec 28 '21 at 21:03
  • No, Python will not raise an exception on subprocess failure unless you specifically request this behavior with `check=True`. You can easily verify this for yourself with `subprocess.run(['false'])` which always fails, by design (except on Windows, which fails by design for other reasons). – tripleee Dec 30 '21 at 06:45
  • for example try this https://queirozf.com/entries/python-3-subprocess-examples in a try/exception clause – Pythonaire Jan 03 '22 at 14:35