I am trying to understand what is the motivation behind using Python's library functions for executing OS-specific tasks such as creating files/directories, changing file attributes, etc. instead of just executing those commands via os.system()
or subprocess.call()
?
For example, why would I want to use os.chmod
instead of doing os.system("chmod...")
?
I understand that it is more "pythonic" to use Python's available library methods as much as possible instead of just executing shell commands directly. But, is there any other motivation behind doing this from a functionality point of view?
I am only talking about executing simple one-line shell commands here. When we need more control over the execution of the task, I understand that using subprocess
module makes more sense, for example.
It's faster, os.system
and subprocess.call
create new processes which is unnecessary for something this simple. In fact, os.system
and subprocess.call
with the shell
argument usually create at least two new processes: the first one being the shell, and the second one being the command that you're running (if it's not a shell built-in like test
).
Some commands are useless in a separate process. For example, if you run os.spawn("cd dir/")
, it will change the current working directory of the child process, but not of the Python process. You need to use os.chdir
for that.
You don't have to worry about special characters interpreted by the shell. os.chmod(path, mode)
will work no matter what the filename is, whereas os.spawn("chmod 777 " + path)
will fail horribly if the filename is something like ; rm -rf ~
. (Note that you can work around this if you use subprocess.call
without the shell
argument.)
You don't have to worry about filenames that begin with a dash. os.chmod("--quiet", mode)
will change the permissions of the file named --quiet
, but os.spawn("chmod 777 --quiet")
will fail, as --quiet
is interpreted as an argument. This is true even for subprocess.call(["chmod", "777", "--quiet"])
.
You have fewer cross-platform and cross-shell concerns, as Python's standard library is supposed to deal with that for you. Does your system have chmod
command? Is it installed? Does it support the parameters that you expect it to support? The os
module will try to be as cross-platform as possible and documents when that it's not possible.
If the command you're running has output that you care about, you need to parse it, which is trickier than it sounds, as you may forget about corner-cases (filenames with spaces, tabs and newlines in them), even when you don't care about portability.