views:

212

answers:

7

Spinning off from another thread, when is it appropriate to use os.system() to issue commands like rm -rf, cd, make, xterm, ls ?

Considering there are analog versions of the above commands (except make and xterm), I'm assuming it's safer to use these built-in python commands instead of using os.system()

Any thoughts? I'd love to hear them.

+14  A: 

Rule of thumb: if there's a built-in Python function to achieve this functionality use this function. Why? It makes your code portable across different systems, more secure and probably faster as there will be no need to spawn an additional process.

Darin Dimitrov
Not to mention: If you need to do it a lot, starting lots of new processes can be a performance problem.
Mattias Nilsson
@Mattias, excellent remark, I've updated my answer to take it into account.
Darin Dimitrov
+4  A: 

Darin's answer is a good start.

Beyond that, it's a matter of how portable you plan to be. If your program is only ever going to run on a reasonably "standard" and "modern" Linux then there's no reason for you to re-invent the wheel; if you tried to re-write make or xterm they'd be sending the men in the white coats for you. If it works and you don't have platform concerns, knock yourself out and simply use Python as glue!

If compatibility across unknown systems was a big deal you could try looking for libraries to do what you need done in a platform independent way. Or you need to look into a way to call on-board utilities with different names, paths and mechanisms depending on which kind of system you're on.

Carl Smotricz
+2  A: 

I would suggest that you only use use os.system for things that there are not already equivalents for within the os module. Why make your life harder?

jathanism
+3  A: 

The only time that os.system might be appropriate is for a quick-and-dirty solution for a non-production script or some kind of testing. Otherwise, it is best to use built-in functions.

krs1
I posted a similar answer before I saw this ...
Lee-Man
+4  A: 

One of the problems with system() is that it implies knowledge of the shell's syntax and language for parsing and executing your command line. This creates potential for a bug where you didn't validate input properly, and the shell might interpet something like variable substitution or determining where an argument begins or ends in a way you don't expect. Also, another OS's shell might have divergent syntax from your own, including very subtle divergence that you won't notice right away. For reasons like these I prefer to use execve() instead of system() -- you can pass argv tokens directly and not have to worry about something in the middle (mis-)parsing your input.

Another problem with system() (this also applies to using execve()) is that when you code that, you are saying, "look for this program, and pass it these args". This makes a couple of assumptions which may lead to bugs. First is that the program exists and can be found in $PATH. Maybe on some system it won't. Second, maybe on some system, or even a future version of your own OS, it will support a different set of options. In this sense, I would avoid doing this unless you are absolutely certain the system you will run on will have the program. (Like maybe you put the callee program on the system to begin with, or the way you invoke it is mandated by something like POSIX.)

Lastly... There's also a performance hit associated with looking for the right program, creating a new process, loading the program, etc. If you are doing something simple like a mv, it's much more efficient to use the system call directly.

These are just a few of the reasons to avoid system(). Surely there are more.

asveikau
+3  A: 

Your question seems to have two parts. You mention calling commands like "xterm", "rm -rf", and "cd".

Side Note: you cannot call 'cd' in a sub-shell. I bet that was a trick question ...

As far as other command-level things you might want to do, like "rm -rf SOMETHING", there is already a python equivalent. This answers the first part of your question. But I suspect you are really asking about the second part.

The second part of your question can be rephrased as "should I use system() or something like the subprocess module?".

I have a simple answer for you: just say NO to using "system()", except for prototyping.

It's fine for verifying that something works, or for that "quick and dirty" script, but there are just too many problems with os.system():

  1. It forks a shell for you -- fine if you need one
  2. It expands wild cards for you -- fine unless you don't have any
  3. It handles redirect -- fine if you want that
  4. It dumps output to stderr/stdout and reads from stdin by default
  5. It tries to understand quoting, but it doesn't do very well (try 'Cmd" > "Ofile')
  6. Related to #5, it doesn't always grok argument boundaries (i.e. arguments with spaces in them might get screwed up)

Just say no to "system()"!

Lee-Man
+1  A: 

The os.system call is starting to be 'frowned upon' in python. The 'new' replacement would be subprocess.call or subprocess.Popen in the subprocess module. Check the docs for subprocess

The other nice thing about subprocess is you can read the stdout and stderr into variables, and process that without having to redirect to other file(s).

Like others have said above, there are modules for most things. Unless you're trying to glue together many other commands, I'd stick with the things included in the library. If you're copying files, use shutil, working with archives you've got modules like tarfile/zipfile and so on.

Good luck.

razzmataz