How to use only a sub shell to execute many commands in python

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri Jan 18 11:49:23 EST 2008


En Fri, 18 Jan 2008 09:31:25 -0200, raocheng <rc.china at gmail.com> escribi�:

> Please see the following code.
> Suppose I have many shell commands to be executed. And I don't want to
> fork a sub shell for each command(eg: status,output =
> commands.getstatusoutput(cmd)) because it is too expensive. I want to
> use only one sub shell to execute all these commands and want to get
> each command's output. How can I accomplish this task ? Thanks in
> advance.

The hard part is to determine WHEN the command has completed its  
execution, because there is no indication of that. One way would be to set  
a relatively uncommon prompt, and look for that string in stdout. You  
can't read beyond that, else the code would block.
Another way is to use a separate thread to read from stdout/stderr, and  
set a timeout; when no more output comes whithin the timeout, you assume  
the command has finished.

The code below uses the first approach, changing the prompt to <$$$>\r\n.  
I've tested it on Windows only, but should work on Linux too with some  
minor modifications.

import subprocess
 from os import getenv

# Windows only, this is to determine the shell in use
# Linux users may try with getenv("SHELL", "sh")
shell = getenv("COMSPEC", "cmd")
p = subprocess.Popen(shell, stdin=subprocess.PIPE,
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT)

expected = '<$$$>\r\n'
cmds = ['prompt $L$$$$$$$G$_','date /t','cd','dir','ipconfig /all']
# The first command above sets an uncommon prompt, ending with a newline.
# On Linux use PS1=whatever, but make sure it ends in \n and set the
# expected variable accordingly.

for cmd in cmds:
     print ">>>",cmd
     p.stdin.write('%s\n' % cmd)
     while True:
         line = p.stdout.readline()
         if line.endswith(expected): break
         print line,

print "Waiting for subshell to terminate"
p.stdin.write("exit\n")
p.wait()
print "Done"


-- 
Gabriel Genellina




More information about the Python-list mailing list