[Twisted-Python] Question on using processes
Tim Allen
screwtape at froup.com
Thu Aug 5 16:12:13 MDT 2004
On 6 Aug 2004, at 06:53, Matt Feifarek wrote:
> I'm using twisted.internet.utils.getProcessOutput() to run commands
> from a reactor.
>
> I've pretty much got this working okay (with a few false starts
> related to how args are put together... you can't send in a big long
> string; you literally have to make a list of argument words... what a
> PITA).
This is due to Python's (and C's) Unix heritage. The kernel call to
spawn a new process takes the full path to the executable, and an array
of null-terminated strings which are the arguments. This can be quite
tedious to set up in C, but shouldn't be too painful under Python.
Contrast this behaviour with MS-DOS and Win32, whose 'new process' API
takes a single string of command-line parameters, and passes that
single string directly to the new process.
When you type a command with some parameters at the command line, how
does the program wind up with a sequence of command-line parameters?
Under Unix, the shell (usually /bin/sh or compatible) reads through the
command-line and does all its special parsing - adding environment
variables, constructing pipes, breaking up the string into
space-delimited chunks, doing backslash-escaping and so forth, it
searches the PATH environment variable for the location of the named
program, and winds up with a full executable path and an array of
string parameters which it hands off to the kernel, and your process is
started. Because most shells have a well-designed meta-character set,
you can spawn pretty much any program you like with pretty much any
command-line you like (except for embedded nulls, of course) grouped in
any way you like.
Under DOS/Win32, the shell (usually CMD.EXE) takes the command-line you
give, searches $PATH for the executable, and hands the executable's
path and the command-line string off to the kernel. The program that's
started is responsible for parsing the given string into a list of
parameters, and of course they all do it slightly differently. Some
don't let you use filenames with spaces, some let you use filenames
with spaces but don't let you use filenames with quotes, and so forth.
For example, under Unix, I can use 'python -c' to make instant Python
scripts:
python -c 'print "Hello, \"World\""'
Under Win32, I don't believe I can do the above step because CMD.EXE
always treats double-quotes as delimiting a filename with spaces. I
can't make a single commandline parameter that includes embedded
quotes.
> Now, I've got a command that needs to pipe something through another
> command, something like this:
>
> /bin/cat foo.txt | /usr/bin/tail
The reason for this is that piping is set up and executed by the shell,
not the kernel. What you really need (to solve both these problems) is
a way to get the shell to do all the dirty work for you - and luckily,
such a feature exists. For the above example, instead of executing
/bin/cat and handing it the other parameters try executing /bin/sh and
giving it the parameters ['-c', '/bin/cat foo.txt | /usr/bin/tail']
More information about the Twisted-Python
mailing list