views:

318

answers:

2

Just what the title says:

  1. The subprocess module cannot be used as this should work on 2.4 and 2.5
  2. Shell process should not be spawned to pass arguments.

To explain (2), consider the following code:

>>> x=os.system('foo arg')
sh: foo: not found
>>> x=os.popen('foo arg')
sh: foo: not found
>>>

As you can see os.system and os.popen runs the given command ("foo") via a system shell ("sh"). I don't want this to happen (otherwise, ugly 'not found' messages are printed to program stderr without my control).

Finally, I should be able to pass arguments to this program ('arg' in the above example).

How would one go about doing this in Python 2.5 and 2.4?

+3  A: 

You probably need to use the subprocess module which is available in Python 2.4

Popen("/home/user/foo" + " arg")

>>> Popen("foo arg", shell=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/subprocess.py", line 595, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1092, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

You will need to include the full path since you aren't using the shell.

http://docs.python.org/library/subprocess.html#replacing-os-system

Alternatively you can also pass subprocess.PIPE to the stderr and stdout to suppress the messages. See the link above for more details.

Unknown
Err, subprocess is available from 2.4? I deluded myself thinking that it is available from 2.6.
Sridhar Ratnakumar
The manual says "new in 2.4"
Unknown
A: 

As previously described, you can (and should) use the subprocess module.

By default, shell parameter is False. This is good, and quite safe. Also, you don't need to pass the full path, just pass the executable name and the arguments as a sequence (tuple or list).

import subprocess

# This works fine
p = subprocess.Popen(["echo","2"])

# These will raise OSError exception:
p = subprocess.Popen("echo 2")
p = subprocess.Popen(["echo 2"])
p = subprocess.Popen(["echa", "2"])

You can also use these two convenience functions already defined in subprocess module:

# Their arguments are the same as the Popen constructor
retcode = subprocess.call(["echo", "2"])
subprocess.check_call(["echo", "2"])

Remember you can redirect stdout and/or stderr to PIPE, and thus it won't be printed to the screen (but the output is still available for reading by your python program). By default, stdout and stderr are both None, which means no redirection, which means they will use the same stdout/stderr as your python program.

Also, you can use shell=True and redirect the stdout.stderr to a PIPE, and thus no message will be printed:

# This will work fine, but no output will be printed
p = subprocess.Popen("echo 2", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# This will NOT raise an exception, and the shell error message is redirected to PIPE
p = subprocess.Popen("echa 2", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Denilson Sá