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?
-
2Running `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
2 Answers
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

- 877
- 6
- 13
-
*"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
-
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

- 175,061
- 34
- 275
- 318